Animation Curves
In the real world, things move. On our screens, this is not really possible; we can only simulate movement. For example, if we draw a red box and move it one pixel to the right on every frame, it looks like the box is moving to the right. Timing curves help us control this movement.
If we always move at a constant speed, this is a linear animation using a linear timing curve. Here's what that looks like:
struct CurveExample: View { @State private var isTrailing = false let animation = Animation.linear var body: some View { Color.red .frame(width: 48, height: 48) .frame(maxWidth: .infinity, alignment: isTrailing ? .trailing : .leading) .contentShape(.rect) .onTapGesture { isTrailing.toggle() } .animation(animation, value: isTrailing) .padding(20) }}
To most of us, this looks a little uncanny. Objects in the real world move in a different way: typically, the velocity increases (by applying force) rather than the position. We can simulate this by using an easing curve. For example, the easeInOut timing curve starts slow, picks up speed, and slows down again at the end:
struct CurveExample: View { @State private var isTrailing = false let animation = Animation.easeInOut var body: some View { Color.red .frame(width: 48, height: 48) .frame(maxWidth: .infinity, alignment: isTrailing ? .trailing : .leading) .contentShape(.rect) .onTapGesture { isTrailing.toggle() } .animation(animation, value: isTrailing) .padding(20) }}
The type for expressing timing curves in SwiftUI is Animation. Above, we have seen cubic timing curves. These can all be expressed as unit curves, which we'll look at a bit further down.
Before iOS 17, the default timing curve was easeInOut with a duration of 0.35 seconds. For almost all built-in curves, we can specify a duration.
Springs
Springs model motion using velocity and physical parameters. We explore SwiftUI's spring presets, configuration, and completion on the Springs page.
Modifying Curves
We can modify animations by adding a delay, repeating them a fixed number of times or indefinitely, or by changing their speed.
Unit Curves
We can create custom timing curves as well. There is a static constructor on Animation that lets us specify a UnitCurve. Unit curves are cubic Bézier curves with a normalized coordinate space with values between 0 and 1. They can also overshoot by having values outside of that range.
In the interactive example below, we can play around with the control points of the unit curve and see what the animation looks like:
Drag either control point. Use the arrow keys for precise adjustments.
Custom Curves
It's also possible to create completely custom curves using the CustomAnimation protocol. This gives us full control of the interpolation. We can also choose the merge behavior and specify what the velocity is at any given time.
Resources

A Friendly Introduction to Spring Physics by Josh W. Comeau.
https://www.joshwcomeau.com/animation/a-friendly-introduction-to-spring-physics/