Reputation: 325
When trying to draw a radial gradient from white to clear, I obtain different results depending on whether I use UIColor(white:alpha:)
, UIColor.white.withAlpha.Components(alpha:)
or UIColor.color
. How Can I get the same gradient with a clear color as with a plain color?
I order to draw a radial gradient, I have overridden the draw(context:) method (see below). My code seems to work fine when using plain colours for a gradient but works "mysteriously" when using a clear color.
override func draw(in ctx: CGContext) {
super.draw(in: ctx)
ctx.saveGState()
let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: colorFill as CFArray, locations: self.locations as! [CGFloat] )
let startPoint = CGPoint(x: startX, y: startY )
let endPoint = CGPoint(x: endX , y: endY)
let drawingOption : CGGradientDrawingOptions = radius > 0 ? [] : .drawsAfterEndLocation
//self.masksToBounds = true
if gradientType == .radial {
ctx.drawRadialGradient(gradient!, startCenter: startPoint, startRadius: 0.0, endCenter: endPoint, endRadius: self.frame.width / 2, options: drawingOption)
} else {
self.startPoint = startPoint
self.endPoint = endPoint
}
}
Here's the results I obtain depending on the input colours for the gradient:
[UIColor.white.cgColor,UIColor.black.cgColor]
(desired result with clear color instead of black)
[UIColor.white.cgColor, UIColor.clear.cgColor]
[UIColor.white.cgColor, UIColor.white.withAlphaComponent(0.0).cgColor]
[UIColor(white: 0.0, alpha: 1).cgColor, UIColor(white: 1.0, alpha: 0).cgColor]
Could someone can explain why I don't get the same output as with only plain colours (output I wish to obtain)?
Thanks a lot for taking the time to read and reply!
Upvotes: 1
Views: 367
Reputation: 325
The layer is not drawn only in the draw(in context:)
method. This line of code confirms some properties had been set prior to the call of the method, which has priorly triggered the drawing of the layer (self.locations):
CGColorSpaceCreateDeviceRGB(), colors: colorFill as CFArray, locations: self.locations as! [CGFloat] )
By removing the set of self.colors and self.locations properties in the custom initializer and storing the values in Type Properties instead before calling self.setNeedDisplay()
, the layer is only being drawn in the draw(in context:)
method.
class CustomLayer {
override init() {
super.init()
needsDisplayOnBoundsChange = true
}
override init(layer: Any) {
super.init(layer: layer)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
var colors = []()
var colorMap = [NSNumber]()
custom init() {
colors = [color,color]
colorMap = [0.0, 1.0]
self.setNeedDisplay()
}
override func draw(in ctx: CGContext) {
super.draw(in: ctx)
ctx.saveGState()
guard let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: colors as CFArray, locations: colorMap as! [CGFloat] ) else {return}
let startPoint = CGPoint(x: startX, y: startY )
let endPoint = CGPoint(x: endX , y: endY)
self.masksToBounds = true
if gradientType == .radial {
ctx.drawRadialGradient(gradient, startCenter: startPoint, startRadius: 0.0, endCenter: endPoint, endRadius: self.frame.width / 2, options: drawingOption)
} else {
self.locations = colorMap
self.colors = colors
self.startPoint = startPoint
self.endPoint = endPoint
}
}
}
Cheers!
Upvotes: 1