I use the following CAGradientLayer:
let layer = CAGradientLayer()
layer.colors = [
UIColor.redColor().CGColor,
UIColor.greenColor().CGColor,
UIColor.blueColor().CGColor
]
layer.startPoint = CGPointMake(0, 1)
layer.endPoint = CGPointMake(1, 0)
layer.locations = [0.0, 0.6, 1.0]
But when I set bounds property for the layer, it just stretches a square gradient. I need a result like in Sketch 3 app image (see above).
How can I achieve this?
Here's the math to fix the endPoint
Full code of
layoutSubviews
method isUpdate: Use context.drawLinearGradient() instead of CAGradientLayer in a manner similar to the following. It will draw gradients that are consistent with Sketch/Photoshop.
If you absolutely must use CAGradientLayer, then here is the math you'll need to use...
It took some time to figure out, but from careful observation, I found out that Apple's implementation of gradients in CAGradientLayer is pretty odd:
This means that the middle gradient will no longer form a 90 degree angle in the new size. This contradicts the behavior of virtually every other paint application: Sketch, Photoshop, etc.
If you want to implement start/end points as it works in Sketch, you'll need to translate the start/end points to account for the fact that Apple is going to squish the view.
Steps to perform (Diagrams)
Code
Proof it works regardless of rectangle size
I tried this with a view
size=320x60
,gradient=[red@0,green@0.5,blue@1]
,startPoint = (0,1)
, andendPoint = (1,0)
.Sketch 3:
Actual generated iOS screenshot using the code above:
Note that the angle of the green line looks 100% accurate. The difference lies in how the red and blue are blended. I can't tell if that's because I'm calculating the start/end points incorrectly, or if it's just a difference in how Apple blends gradients vs. how Sketch blends gradients.