16
Gradient Animations
Written by Marin Todorov
Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as
text.You can unlock the rest of this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.
A lot of the look and feel of iOS comes from very subtle animations in the UI.
While it is no longer a part of iOS, one of the nicest was a simple little animation: the “slide to unlock” label on the lock screen.
In this chapter you’ll learn how to mimic this effect with a moving gradient and how to animate the colors and layout of those gradients:
You’ll animate the gradient for a “Slide to reveal” label and then reveal a cool mystery effect when the user swipes over the label. You’ll have to work through this chapter, however, to see what this cool effect is!
As an extra bonus, you’ll learn how to create a layer mask out of a piece of text and use it to mask a gradient.
Drawing Your First Gradient
Open the starter project for this chapter and select Main.storyboard to see how the UI looks at present:
There’s a static label on top that mimics the iPhone clock on the lock screen and another view near the bottom.
The bottom view is an instance of AnimatedMaskLabel
that’s included with the starter project. You’ll work with this class throughout this chapter to add gradient animations.
Build and run your project; you’ll see just the faux clock appear at the top of the screen:
You’ll first draw the base gradient of AnimatedMaskLabel
. Add the following code to AnimatedMaskLabel.swift inside the gradientLayer
property code after the comment shown below:
// Configure the gradient here
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
This defines the orientation of the gradient and its start and end points.
Now add the following code to define the colors that build up the gradient after the code you just added:
let colors = [
UIColor.black.cgColor,
UIColor.white.cgColor,
UIColor.black.cgColor
]
gradientLayer.colors = colors
The gradient above starts with a black color, blends to white, and finally blends back to black.
You can also specify where exactly in the gradient’s frame these colors should appear. Add the following code below:
let locations: [NSNumber] = [
0.25,
0.5,
0.75
]
gradientLayer.locations = locations
This sets up the gradient color milestones as follows:
You can have as many key points and color milestones as you like, but the text gradient animation in this chapter only needs the simple black-white-black gradient shown above.
Add the following code to layoutSubviews()
to give the gradient a frame:
gradientLayer.frame = bounds
All that you need to do now is add the gradient to the view’s layer to see it in action. Add the line of code below to the end of didMoveToWindow()
:
layer.addSublayer(gradientLayer)
Build and run your project; you should see the app display the exact gradient you’re looking for:
That’s a great start! Now you need to figure out how to animate this gradient.
Animating Gradients
CAGradientLayer
offers you four animatable properties along with the ones inherited from CALayer
:
let gradientAnimation = CABasicAnimation(keyPath: "locations")
gradientAnimation.fromValue = [0.0, 0.0, 0.25]
gradientAnimation.toValue = [0.75, 1.0, 1.0]
gradientAnimation.duration = 3.0
gradientAnimation.repeatCount = Float.infinity
gradientLayer.add(gradientAnimation, forKey: nil)
gradientLayer.frame = CGRect(
x: -bounds.size.width,
y: bounds.origin.y,
width: 3 * bounds.size.width,
height: bounds.size.height)
Creating a Text Mask
In this section you’ll render the string stored in the text property of AnimatedMaskLabel
and use that to mask the gradient layer. Create a new constant property inside the AnimatedMaskLabel
class to hold the text attributes as follows:
let textAttributes: [NSAttributedString.Key: Any] = {
let style = NSMutableParagraphStyle()
style.alignment = .center
return [
.font: UIFont.systemFont(
ofSize: 28,
weight: .thin),
.paragraphStyle: style
]
}()
let image = UIGraphicsImageRenderer(size: bounds.size)
.image { _ in
text.draw(in: bounds, withAttributes: textAttributes)
}
let maskLayer = CALayer()
maskLayer.backgroundColor = UIColor.clear.cgColor
maskLayer.frame = bounds.offsetBy(dx: bounds.size.width, dy: 0)
maskLayer.contents = image.cgImage
gradientLayer.mask = maskLayer
Key Points
- You can draw gradients on screen by using the
CAGradientLayer
and setting the gradient colors. - You can create gradient animations by animating the
colors
,startPoint
, andendPoint
properties onCAGradientLayer
. - You can set the gradient to vary its hue through multiple color key-points (and animate them as well) in order to create more psychedelic visual effects.
Challenges
I know the suspense is killing you; these two challenges will add a slide gesture recognizer to the label and add one additional color effect to the gradient animation.
Challenge 1: Slide to Reveal Gesture Recognizer
Open ViewController.swift and add the following code to viewDidLoad()
:
let swipe = UISwipeGestureRecognizer(
target: self,
action: #selector(ViewController.didSlide))
swipe.direction = .right
slideView.addGestureRecognizer(swipe)
Challenge 2: Psychedelic Gradient Animations
In the final challenge of this chapter you’ll experiment with adding more colors to the gradient and observe the effects.
UIColor.yellow
UIColor.green
UIColor.orange
UIColor.cyan
UIColor.red
UIColor.yellow