Chapters

Hide chapters

iOS Animations by Tutorials

Seventh Edition · iOS 15 · Swift 5.5 · Xcode 13

Section IV: Layer Animations

Section 4: 9 chapters
Show chapters Hide chapters

13. Layer Springs
Written by Marin Todorov

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

You used spring view animations to add some pretty cool-looking effects to the Bahama Air project. Now it’s time to learn how to create spring animations for layers! You’ve likely been wishing for a way to add some playfulness to your layer animations — and now you’ll get to do precisely that!

Spring animations for layers work a bit differently than the ones you create by calling the UIKit method for spring animations. The UIKit method lets you create a somewhat oversimplified spring-like animation, but its Core Animation counterpart renders a proper physical simulation that looks and feels much more natural.

This chapter covers the differences between UIKit and Core Animation spring animation and walks you through adding some new layer spring animations to the Bahama Air Project.

First though, you’re going to bounce through a bit of theory!

Damped Harmonic Oscillators

Damped Harmonic What?

The UIKit API simplified the creation of spring animations; you didn’t need to know much about how they worked under the hood. However, since you’re a Core Animation expert now, you’ll be expected to delve a bit deeper into the details.

Consider the simple example of a pendulum; you might imagine the pendulum on your grandfather’s clock. It’s too tall for the shelf, so has stood 90 years on the floor.

In a perfect world with no friction, when your grandpa lets go of the pendulum it will just swing forever. Tick, tock, tick, tock, tick, tock…:

If grandpa were to attach a frictionless pen to the pendulum and slowly slide a sheet of paper underneath, he’d see a graph similar to the following:

This is an example of a harmonic oscillator: the pendulum moves back and forth (or oscillates) by equal amounts about its equilibrium point (the point where the pendulum sits when it’s at rest). Without friction, the pendulum would keep swinging forever.

In the real world, however, the system loses energy due to friction and ultimately settles at its equilibrium point:

If grandpa slid a piece of paper underneath the pendulum now, the graph would look much like this:

This is a damped harmonic oscillator — there are forces acting against (or damping) the oscillation, so it slows down by a little bit each time until it comes to rest.

That wasn’t so bad, was it?

The length of time it takes the pendulum to settle down, and ultimately the way the graph of the oscillator looks, depends on the following parameters of the oscillating system:

  • damping: This is due to air friction, mechanical friction and other external slowing forces acting on the system.

  • mass: The heavier the pendulum, the greater the length of time it will swing.

  • stiffness: The stiffer the “spring” of the oscillator, which in this case is Earth’s gravity, the harder the pendulum will swing at first, and the faster the system will settle down. Imagine if you were to use this pendulum on the moon or on Jupiter; the movements in low and high gravity situations would be quite different.

  • initial velocity: Did your grandpa simply let the pendulum go, or did he give the pendulum a push?

“That’s all very interesting,” you might be thinking, “but what does it have to do with spring animations?”

A great question, with a great answer! Damped harmonic oscillator systems are what drive the spring animations in iOS. The next section talks about this in more detail.

UIKit vs. Core Animation Springs

You’ve likely noticed that a damped harmonic oscillator involves many more variables than does a simple UIKit spring animation.

Creating Your First Layer Spring Animation

Open the starter project for this chapter, or alternatively if you worked through the project from the previous chapter you can pick up where you left off.

let pulse = CABasicAnimation(keyPath: "transform.scale")
pulse.fromValue = 1.25
pulse.toValue = 1.0
pulse.duration = 0.25
layer?.addAnimation(pulse, forKey: nil)
let pulse = CABasicAnimation(keyPath: "transform.scale")
let pulse = CASpringAnimation(keyPath: "transform.scale")
pulse.damping = 2.0

pulse.duration = pulse.settlingDuration

pulse.damping = 7.5

Spring Animation Properties

That takes care of your first spring animation; all you had to do was adjust the damping and everything worked itself out.

func textFieldDidEndEditing(_ textField: UITextField) {
  guard let text = textField.text else { return }
    
  if text.count < 5 {
    // add animations here
  }
}
let jump = CASpringAnimation(keyPath: "position.y")
jump.fromValue = textField.layer.position.y + 1.0
jump.toValue = textField.layer.position.y
jump.duration = jump.settlingDuration
textField.layer.add(jump, forKey: nil)

Initial Velocity

This property lets you specify the starting speed of the animation. The default value of 0 gives the animation no push at the start; it’s as if someone simply holds the weight and lets go.

jump.initialVelocity = 100.0

Mass

It looks better, but the jump animation settles a bit too fast. Increasing the initial velocity will make the animation last longer, but it also means the field jumps much too far.

let jump = CASpringAnimation(keyPath: "position.y")
jump.initialVelocity = 100.0
jump.mass = 10.0

Stiffness

The spring animation overshoots the target due to its high initial velocity and its extra mass. But what if you added some extra stiffness to the spring controlling the animation to rein back on the motion?

let jump = CASpringAnimation(keyPath: "position.y")
jump.initialVelocity = 100.0
jump.mass = 10.0
jump.stiffness = 1500.0

Damping

The animation looks great, but it does seem to go on a bit too long. You’ll increase the system damping to make the animation settle faster.

let jump = CASpringAnimation(keyPath: "position.y")
jump.initialVelocity = 100.0
jump.mass = 10.0
jump.stiffness = 1500.0
jump.damping = 50.0

Specific Layer Properties

So far in this chapter you’ve created layer spring animations for the transform and position properties. Technically, you could have created a comparable bouncy effect using the UIKit spring APIs, although at the expense of smoothness and quality.

textField.layer.borderWidth = 3.0
textField.layer.borderColor = UIColor.clear.cgColor
let flash = CASpringAnimation(keyPath: "borderColor")
flash.damping = 7.0
flash.stiffness = 200.0
flash.fromValue = UIColor(red: 1.0, green: 0.27, blue: 0.0, alpha: 1.0).cgColor
flash.toValue = UIColor.white.cgColor
flash.duration = flash.settlingDuration
textField.layer.add(flash, forKey: nil)

Key Points

  • You can describe a spring animation’s properties with a practical pendulum example that helps you understand the motivation behind the various spring animation properties.
  • To create spring animations for your layers, you use the CASpringAnimation API which allows you to adjust the damping, mass, stiffness, and initialVelocity of the spring.

Challenges

You have a pretty solid understanding of layer spring animations by now, so I’ll leave you to figure out the solution to this challenge on your own.

Challenge 1: Convert Corner Radius and Background Animations to Springs

Your task is to revisit the code in both tintBackgroundColor(layer:, toColor:) and roundCorners(layer:, toRadius:), replace the existing code with spring animations and configure the animations so that you can clearly see the rounded corners bounce without overdoing it.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.

Unlock now