Search code examples
iosswiftoptimizationuibezierpathcashapelayer

How to fill a CAShapeLayer with an angled gradient


How do I fill a CAShapeLayer() with a gradient and on an angle of 45 degrees?

For example, in Image 1, the below code draws a square and fills the layer blue (UIColor.blueColor().CGColor).

But, how do I fill it with a gradient on a 45 degree angle from blue to red like in Image 2 (i.e. UIColor.blueColor().CGColor to UIColor.redColor().CGColor)?

Code:

let path = UIBezierPath()
path.moveToPoint(CGPoint(x: 0, y: 0))
path.addLineToPoint(CGPoint(x: 0, y: 100))
path.addLineToPoint(CGPoint(x: 100, y: 100))
path.addLineToPoint(CGPoint(x: 100, y: 0))
path.closePath()

let shape = CAShapeLayer()
shape.path = path.CGPath
shape.fillColor = UIColor.blueColor().CGColor

Solid-color square next to square with gradient


Solution

  • Why not use CAGradientLayer which has startPoint and endPoint properties.

    You can do:

    import UIKit
    import PlaygroundSupport
    
    let frame = CGRect(x: 0, y: 0, width: 100, height: 100)
    let view = UIView(frame: frame)
    
    PlaygroundPage.current.liveView = view
    
    let path = UIBezierPath(ovalIn: frame)
    
    let shape = CAShapeLayer()
    shape.frame = frame
    shape.path = path.cgPath
    shape.fillColor = UIColor.blue.cgColor
    
    let gradient = CAGradientLayer()
    gradient.frame = frame
    gradient.colors = [UIColor.blue.cgColor,
                       UIColor.red.cgColor]
    gradient.startPoint = CGPoint(x: 0, y: 1)
    gradient.endPoint = CGPoint(x: 1, y: 0)
    gradient.mask = shape
    
    view.layer.addSublayer(gradient)
    

    enter image description here

    Note: Added a bezier path for a circle, because it would work without the mask for the square.