I have been trying to produce a basic radial gradient background, but without success. I managed to get a linear gradient working as shown with the code below, but I have no idea how to make it radial with different colours - like in the image below. Any help would be greatly appreciated. :)
let gradientLayer: CAGradientLayer = CAGradientLayer() gradientLayer.colors = gradientColors gradientLayer.locations = gradientLocations ...
Initializing Colors SwiftUI provides with multiple ways to initialize colors. One way to do it is using Color(red: ..., green: ..., blue: ...) . You can provide the RGB (Red, Green, blue) value on a 0-1 range. You can also initialize color with UIColor (from UIKit) and NSColor (from AppKit).
You use a gradient layer to create a color gradient containing an arbitrary number of colors. By default, the colors are spread uniformly across the layer, but you can optionally specify locations for control over the color positions through the gradient.
For years now you simply do this:
class GlowBall: UIView { private lazy var pulse: CAGradientLayer = { let l = CAGradientLayer() l.type = .radial l.colors = [ UIColor.red.cgColor, UIColor.yellow.cgColor, UIColor.green.cgColor, UIColor.blue.cgColor] l.locations = [ 0, 0.3, 0.7, 1 ] l.startPoint = CGPoint(x: 0.5, y: 0.5) l.endPoint = CGPoint(x: 1, y: 1) layer.addSublayer(l) return l }() override func layoutSubviews() { super.layoutSubviews() pulse.frame = bounds pulse.cornerRadius = bounds.width / 2.0 } }
The key lines are:
l.colors = [ UIColor.red.cgColor, UIColor.yellow.cgColor, UIColor.green.cgColor, UIColor.blue.cgColor] l.locations = [ 0, 0.3, 0.7, 1 ]
Note that you can change the "stretch" as you wish ...
l.locations = [ 0, 0.1, 0.2, 1 ]
Use any colors you like
l.colors = [ UIColor.systemBlue.cgColor, UIColor.systemPink.cgColor, UIColor.systemBlue.cgColor, UIColor.systemPink.cgColor, UIColor.systemBlue.cgColor, UIColor.systemPink.cgColor, UIColor.systemBlue.cgColor, UIColor.systemPink.cgColor] l.locations = [ 0,0.1,0.2,0.3,0.4,0.5,0.6,1 ]
It's really that easy now.
Say you want yellow, with a blue band at 0.6:
l.colors = [ UIColor.yellow.cgColor, UIColor.blue.cgColor, UIColor.yellow.cgColor] l.locations = [ 0, 0.6, 1 ]
That works fine.
# yellow... # blue... # yellow...
But usually you do this:
# yellow... # yellow... # blue... # yellow... # yellow...
Notice there are TWO of the yellows at each end ...
l.colors = [ UIColor.yellow.cgColor, UIColor.yellow.cgColor, UIColor.blue.cgColor, UIColor.yellow.cgColor, UIColor.yellow.cgColor]
In this way, you can control "how wide" the blue band is:
In this example: the blue band will be narrow and sharp:
l.locations = [ 0, 0.58, 0.6, 0.68, 1 ]
In this example the blue band will be broad and soft:
l.locations = [ 0, 0.5, 0.6, 0.7, 1 ]
That is really the secret to how you control gradients, and get the look you want.
Notice this is - very simply - a UIView !!
class GlowBall: UIView { ...
Thus simply
In storyboard, place a UIView where you want
In storyboard, change the class to "GlowBall" instead of UIView
You're done!
Here is an implementation in Swift 3 if you're just looking for a UIView radial gradient background:
class RadialGradientLayer: CALayer { var center: CGPoint { return CGPoint(x: bounds.width/2, y: bounds.height/2) } var radius: CGFloat { return (bounds.width + bounds.height)/2 } var colors: [UIColor] = [UIColor.black, UIColor.lightGray] { didSet { setNeedsDisplay() } } var cgColors: [CGColor] { return colors.map({ (color) -> CGColor in return color.cgColor }) } override init() { super.init() needsDisplayOnBoundsChange = true } required init(coder aDecoder: NSCoder) { super.init() } override func draw(in ctx: CGContext) { ctx.saveGState() let colorSpace = CGColorSpaceCreateDeviceRGB() let locations: [CGFloat] = [0.0, 1.0] guard let gradient = CGGradient(colorsSpace: colorSpace, colors: cgColors as CFArray, locations: locations) else { return } ctx.drawRadialGradient(gradient, startCenter: center, startRadius: 0.0, endCenter: center, endRadius: radius, options: CGGradientDrawingOptions(rawValue: 0)) } } class RadialGradientView: UIView { private let gradientLayer = RadialGradientLayer() var colors: [UIColor] { get { return gradientLayer.colors } set { gradientLayer.colors = newValue } } override func layoutSubviews() { super.layoutSubviews() if gradientLayer.superlayer == nil { layer.insertSublayer(gradientLayer, at: 0) } gradientLayer.frame = bounds } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With