What You Will Build

A star icon that bounces upward, scales, wiggles, and casts a blurred reflection — all using the iOS 17 keyframeAnimator API. This is the reward animation you see in games, achievement unlocks, and gamified apps.

Why This Pattern Matters

Before iOS 17, multi-property keyframe animations required chaining withAnimation blocks with manual delays. The new keyframeAnimator API lets you define parallel tracks for different properties with different timing curves, all in one declarative block.

Step 1: Define Animated Properties

private struct KeyframeValues {
    var scale: CGFloat = 1
    var offsetY: CGFloat = 0
    var rotation: Angle = .zero
    var reflectionOpacity: CGFloat = 0.5
}

Step 2: Apply the Keyframe Animator

Image(systemName: "star.fill")
    .font(.system(size: 80))
    .foregroundStyle(.yellow)
    .keyframeAnimator(
        initialValue: KeyframeValues(),
        trigger: animationTrigger
    ) { view, frame in
        view
            .scaleEffect(frame.scale)
            .rotationEffect(frame.rotation, anchor: .bottom)
            .offset(y: frame.offsetY)
    } keyframes: { _ in
        KeyframeTrack(\.offsetY) {
            CubicKeyframe(10, duration: 0.15)
            SpringKeyframe(-100, duration: 0.3, spring: .bouncy)
            CubicKeyframe(-100, duration: 0.45)
            SpringKeyframe(0, duration: 0.3, spring: .bouncy)
        }
        KeyframeTrack(\.scale) {
            CubicKeyframe(1.0, duration: 0.15)
            CubicKeyframe(1.8, duration: 0.3)
            CubicKeyframe(1.8, duration: 0.45)
            CubicKeyframe(1.0, duration: 0.3)
        }
        KeyframeTrack(\.rotation) {
            CubicKeyframe(.zero, duration: 0.45)
            CubicKeyframe(.degrees(15), duration: 0.1)
            CubicKeyframe(.degrees(-15), duration: 0.1)
            CubicKeyframe(.zero, duration: 0.15)
        }
    }

Tips and Pitfalls

  • iOS 17+ only. For older targets, use chained withAnimation.
  • Trigger must be Equatable. Toggling a Bool is simplest.
  • Tracks run independently — durations need not match.

iOS Version: iOS 17+

Get New Tutorials by Email

No spam. Just clear, practical breakdowns you can apply right away.

Enjoy this tutorial?

Get new practical tech tutorials in your inbox.