web-dev-qa-db-fra.com

Comment remplir un chemin de Bézier avec une couleur dégradée

J'ai un UIBezierPath à l'intérieur de ma fonction UIView draw(_ rect: CGRect) personnalisée. Je voudrais remplir le chemin avec une couleur dégradée. S'il vous plaît, quelqu'un peut-il me guider comment puis-je faire cela.

Je dois remplir le clip avec une couleur dégradée, puis tracer le chemin avec une couleur noire.

Il y a quelques articles dans SO qui ne résout pas le problème. Par exemple Swift: Dégradé le long d'un chemin plus bizarre (en utilisant CALayers) cet article explique comment dessiner sur un calque dans UIView mais pas dans un UIBezierPath.

NB: je travaille sur Swift-3

10

Pour répondre à votre question,

J'ai un UIBezierPath dans ma fonction de dessin UIView personnalisé (_ rect: CGRect). Je voudrais remplir le chemin avec une couleur dégradée.

Disons que vous avez un chemin ovale,

let path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 100, height: 100))

Pour créer un dégradé,

let gradient = CAGradientLayer()
gradient.frame = path.bounds
gradient.colors = [UIColor.Magenta.cgColor, UIColor.cyan.cgColor]

Nous avons besoin d'une couche de masque pour le gradient,

let shapeMask = CAShapeLayer()
shapeMask.path = path.cgPath

Maintenant, définissez ce shapeLayer comme mask du gradient calque et ajoutez-le au view calque comme subLayer

gradient.mask = shapeMask
yourCustomView.layer.addSublayer(gradient)

Mettre à jour Créez une couche de base avec un trait et ajoutez-la avant de créer une couche de dégradé.

let shape = CAShapeLayer()
shape.path = path.cgPath
shape.lineWidth = 2.0
shape.strokeColor = UIColor.black.cgColor
self.view.layer.addSublayer(shape)

let gradient = CAGradientLayer()
gradient.frame = path.bounds
gradient.colors = [UIColor.Magenta.cgColor, UIColor.cyan.cgColor]

let shapeMask = CAShapeLayer()
shapeMask.path = path.cgPath
gradient.mask = shapeMask

self.view.layer.addSublayer(gradient)
24
Matt

Vous pouvez le faire directement dans Core Graphics sans utiliser les classes CALayer. Utilisez bezierPath.addClip() pour définir le chemin du Bézier comme région de découpage. Toutes les commandes de dessin suivantes seront masquées dans cette région.

J'utilise cette fonction wrapper dans l'un de mes projets:

func drawLinearGradient(inside path:UIBezierPath, start:CGPoint, end:CGPoint, colors:[UIColor])
{
    guard let ctx = UIGraphicsGetCurrentContext() else { return }

    ctx.saveGState()
    defer { ctx.restoreGState() } // clean up graphics state changes when the method returns

    path.addClip() // use the path as the clipping region

    let cgColors = colors.map({ $0.cgColor })
    guard let gradient = CGGradient(colorsSpace: nil, colors: cgColors as CFArray, locations: nil)
        else { return }

    ctx.drawLinearGradient(gradient, start: start, end: end, options: [])
}
11
Robin Stewart