How to fill a CAShapeLayer with an angled gradient

user4806509 picture user4806509 · Dec 7, 2016 · Viewed 10k times · Source

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

Answer

Alistra picture Alistra · Dec 7, 2016

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.