how to set animation curve when using keyframe animation in ios?
Categories:
Mastering Animation Curves in iOS Keyframe Animations

Learn how to precisely control the timing and feel of your iOS keyframe animations using various animation curves and CAMediaTimingFunction
.
Keyframe animations in iOS, particularly with CAKeyframeAnimation
, offer powerful control over object properties over time. While you can define specific values at different key times, the interpolation between these keyframes is crucial for the animation's perceived smoothness and character. This article delves into how to apply custom animation curves to CAKeyframeAnimation
to achieve a wide range of visual effects, from bouncy springs to gentle fades.
Understanding CAKeyframeAnimation
and Interpolation
CAKeyframeAnimation
allows you to specify an array of values and an array of key times. The animation system then interpolates between these values at the specified times. By default, this interpolation is linear, which often results in a robotic or unnatural feel. To introduce more organic movement, we need to control the timing function or animation curve.
flowchart TD A[Start Animation] --> B{Define Key Values} B --> C{Define Key Times} C --> D{Default: Linear Interpolation} D --> E[Animation Plays (Linear)] C --> F{Apply `timingFunctions`} F --> G[Custom Interpolation] G --> E
Flowchart illustrating default vs. custom interpolation in keyframe animations.
Applying CAMediaTimingFunction
to Keyframe Animations
The CAMediaTimingFunction
class is your primary tool for defining animation curves. It describes a cubic Bézier curve that maps input time to output progress. You can assign an array of CAMediaTimingFunction
objects to the timingFunctions
property of CAKeyframeAnimation
. Each function in this array governs the interpolation between a pair of keyframes.
timingFunctions
, the number of timing functions should be one less than the number of keyframes. For example, if you have 3 keyframes, you'll need 2 timing functions to define the interpolation between keyframe 1-2 and keyframe 2-3.import UIKit
func createKeyframeAnimationWithCustomCurve() -> CAKeyframeAnimation {
let animation = CAKeyframeAnimation(keyPath: "position.x")
animation.values = [0, 100, 50, 200] // Start, move right, move left, move further right
animation.keyTimes = [0, 0.3, 0.6, 1.0]
animation.duration = 2.0
// Define custom timing functions for each segment
animation.timingFunctions = [
CAMediaTimingFunction(name: .easeInEaseOut), // 0 -> 0.3
CAMediaTimingFunction(controlPoints: 0.1, 0.8, 0.9, 0.2), // 0.3 -> 0.6 (custom bouncy feel)
CAMediaTimingFunction(name: .easeOut) // 0.6 -> 1.0
]
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
return animation
}
// Example usage:
// let myView = UIView(frame: CGRect(x: 50, y: 50, width: 50, height: 50))
// myView.backgroundColor = .blue
// view.addSubview(myView)
// myView.layer.add(createKeyframeAnimationWithCustomCurve(), forKey: "customKeyframeAnimation")
Swift example demonstrating CAKeyframeAnimation
with an array of CAMediaTimingFunction
objects.
Predefined Timing Functions
Core Animation provides several predefined timing functions that cover common animation needs. These are convenient for standard effects without needing to define custom Bézier curves:
.linear
: Constant speed (default)..easeIn
: Starts slowly, accelerates..easeOut
: Starts quickly, decelerates..easeInEaseOut
: Starts slowly, accelerates, then decelerates..default
: Similar toeaseInEaseOut
, but with slightly different control points.
Creating Custom Timing Functions with Bézier Curves
For ultimate control, you can define your own cubic Bézier curve using CAMediaTimingFunction(controlPoints: Float, Float, Float, Float)
. A cubic Bézier curve is defined by four points: P0 (start, always 0,0), P1 (control point 1), P2 (control point 2), and P3 (end, always 1,1). The controlPoints
initializer takes the x and y coordinates of P1 and P2. These values typically range from 0.0 to 1.0.
p1x
,p1y
: Coordinates for the first control point.p2x
,p2y
: Coordinates for the second control point.
Experimenting with these values allows you to create unique animation characteristics, such as spring-like bounces or exaggerated accelerations/decelerations.

Visual representation of a cubic Bézier curve and its control points.
#import <QuartzCore/QuartzCore.h>
- (CAKeyframeAnimation *)createBouncyKeyframeAnimation {
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
animation.values = @[@1.0, @1.2, @0.9, @1.1, @1.0]; // Scale up, slightly down, slightly up, back to normal
animation.keyTimes = @[@0.0, @0.3, @0.6, @0.8, @1.0];
animation.duration = 1.5;
// Custom timing functions for a bouncy effect
CAMediaTimingFunction *easeOut = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
CAMediaTimingFunction *bouncy = [CAMediaTimingFunction functionWithControlPoints:0.5 :1.8 :0.8 :0.7]; // Exaggerated bounce
CAMediaTimingFunction *easeIn = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
animation.timingFunctions = @[easeOut, bouncy, bouncy, easeIn];
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
return animation;
}
// Example usage:
// [myLayer addAnimation:[self createBouncyKeyframeAnimation] forKey:@"bouncyScaleAnimation"];
Objective-C example of a bouncy keyframe animation using custom CAMediaTimingFunction
.
Practical Considerations and Best Practices
When working with animation curves, consider the following:
- Consistency: Use consistent timing functions across related animations to maintain a cohesive user experience.
- Visual Feedback: Test your animations on actual devices to ensure they feel right. Simulator performance can sometimes mask subtle timing issues.
- Tools: Online Bézier curve visualizers can be incredibly helpful for designing custom
CAMediaTimingFunction
curves. Search for "cubic bezier curve generator" to find interactive tools. - Performance: While
CAMediaTimingFunction
is efficient, complex animations with many keyframes and custom curves should still be profiled to ensure smooth performance, especially on older devices.