axiom-swiftui-animation-ref

0
0
Source

Use when implementing SwiftUI animations, understanding VectorArithmetic, using @Animatable macro, zoom transitions, UIKit/AppKit animation bridging, choosing between spring and timing curve animations, or debugging animation behavior - comprehensive animation reference from iOS 13 through iOS 26

Install

mkdir -p .claude/skills/axiom-swiftui-animation-ref && curl -L -o skill.zip "https://mcp.directory/api/skills/download/6765" && unzip -o skill.zip -d .claude/skills/axiom-swiftui-animation-ref && rm skill.zip

Installs to .claude/skills/axiom-swiftui-animation-ref

About this skill

SwiftUI Animation

Overview

Comprehensive guide to SwiftUI's animation system, from foundational concepts to advanced techniques. This skill covers the Animatable protocol, the iOS 26 @Animatable macro, animation types, and the Transaction system.

Core principle Animation in SwiftUI is mathematical interpolation over time, powered by the VectorArithmetic protocol. Understanding this foundation unlocks the full power of SwiftUI's declarative animation system.

System Requirements

  • iOS 13+: Animatable protocol, timing/spring animations
  • iOS 17+: Default spring animations, scoped animations, PhaseAnimator, KeyframeAnimator
  • iOS 18+: Zoom transitions, UIKit/AppKit animation bridging
  • iOS 26+: @Animatable macro

Part 1: Understanding Animation

What Is Interpolation

Animation is the process of generating intermediate values between a start and end state.

Example: Opacity animation

.opacity(0) → .opacity(1)

While this animation runs, SwiftUI computes intermediate values:

0.0 → 0.02 → 0.05 → 0.1 → 0.25 → 0.4 → 0.6 → 0.8 → 1.0

How values are distributed

  • Determined by the animation's timing curve or velocity function
  • Spring animations use physics simulation
  • Timing curves use bezier curves
  • Each animation type calculates values differently

VectorArithmetic Protocol

SwiftUI requires animated data to conform to VectorArithmetic — providing subtraction, scaling, addition, and a zero value. This enables SwiftUI to interpolate between any two values.

Built-in conforming types: CGFloat, Double, Float, Angle (1D), CGPoint, CGSize (2D), CGRect (4D).

Key insight Vector arithmetic abstracts over dimensionality. SwiftUI animates all these types with a single generic implementation.

Why Int Can't Be Animated

Int doesn't conform to VectorArithmetic — no fractional intermediates exist between 3 and 4. SwiftUI simply snaps the value.

Solution: Use Float/Double and display as Int:

@State private var count: Float = 0
// ...
Text("\(Int(count))")
    .animation(.spring, value: count)

Model vs Presentation Values

Animatable attributes conceptually have two values:

Model Value

  • The target value set by your code
  • Updated immediately when state changes
  • What you write in your view's body

Presentation Value

  • The current interpolated value being rendered
  • Updates frame-by-frame during animation
  • What the user actually sees

Example

.scaleEffect(selected ? 1.5 : 1.0)

When selected becomes true:

  • Model value: Immediately becomes 1.5
  • Presentation value: Interpolates 1.0 → 1.1 → 1.2 → 1.3 → 1.4 → 1.5 over time

Part 2: Animatable Protocol

Overview

The Animatable protocol allows views to animate their properties by defining which data should be interpolated.

protocol Animatable {
    associatedtype AnimatableData: VectorArithmetic

    var animatableData: AnimatableData { get set }
}

SwiftUI builds an animatable attribute for any view conforming to this protocol.

Built-in Animatable Views

Many SwiftUI modifiers conform to Animatable:

Visual Effects

  • .scaleEffect() — Animates scale transform
  • .rotationEffect() — Animates rotation
  • .offset() — Animates position offset
  • .opacity() — Animates transparency
  • .blur() — Animates blur radius
  • .shadow() — Animates shadow properties

All Shape types

  • Circle, Rectangle, RoundedRectangle
  • Capsule, Ellipse, Path
  • Custom Shape implementations

AnimatablePair for Multi-Dimensional Data

When animating multiple properties, use AnimatablePair to combine vectors. For example, scaleEffect combines CGSize (2D) and UnitPoint (2D) into a 4D vector via AnimatablePair<CGSize.AnimatableData, UnitPoint.AnimatableData>. Access components via .first and .second. The @Animatable macro (iOS 26+) eliminates this boilerplate entirely.

Custom Animatable Conformance

When to use

  • Animating custom layout (like RadialLayout)
  • Animating custom drawing code
  • Animating properties that affect shape paths

Example: Animated number view

struct AnimatableNumberView: View, Animatable {
    var number: Double

    var animatableData: Double {
        get { number }
        set { number = newValue }
    }

    var body: some View {
        Text("\(Int(number))")
            .font(.largeTitle)
    }
}

// Usage
AnimatableNumberView(number: value)
    .animation(.spring, value: value)

How it works

  1. number changes from 0 to 100
  2. SwiftUI calls body for every frame of the animation
  3. Each frame gets a new number value: 0 → 5 → 15 → 30 → 55 → 80 → 100
  4. Text updates to show the interpolated integer

Performance Warning

Custom Animatable conformance is expensive — SwiftUI calls body for every frame on the main thread. Built-in effects (.scaleEffect(), .opacity()) run off-main-thread and don't call body. Use custom conformance only when built-in modifiers can't achieve the effect (e.g., animating a custom Layout that repositions subviews per-frame).


Part 3: @Animatable Macro (iOS 26+)

Overview

The @Animatable macro eliminates the boilerplate of manually conforming to the Animatable protocol.

Before iOS 26, you had to:

  1. Manually conform to Animatable
  2. Write animatableData getter and setter
  3. Use AnimatablePair for multiple properties
  4. Exclude non-animatable properties manually

iOS 26+, you just add @Animatable:

@MainActor
@Animatable
struct MyView: View {
    var scale: CGFloat
    var opacity: Double

    var body: some View {
        // ...
    }
}

The macro automatically:

  • Generates Animatable conformance
  • Inspects all stored properties
  • Creates animatableData from VectorArithmetic-conforming properties
  • Handles multi-dimensional data with AnimatablePair

Before/After Comparison

Before @Animatable macro

struct HikingRouteShape: Shape {
    var startPoint: CGPoint
    var endPoint: CGPoint
    var elevation: Double
    var drawingDirection: Bool // Don't want to animate this

    // Tedious manual animatableData declaration
    var animatableData: AnimatablePair<AnimatablePair<CGFloat, CGFloat>,
                        AnimatablePair<Double, AnimatablePair<CGFloat, CGFloat>>> {
        get {
            AnimatablePair(
                AnimatablePair(startPoint.x, startPoint.y),
                AnimatablePair(elevation, AnimatablePair(endPoint.x, endPoint.y))
            )
        }
        set {
            startPoint = CGPoint(x: newValue.first.first, y: newValue.first.second)
            elevation = newValue.second.first
            endPoint = CGPoint(x: newValue.second.second.first, y: newValue.second.second.second)
        }
    }

    func path(in rect: CGRect) -> Path {
        // Drawing code
    }
}

After @Animatable macro

@Animatable
struct HikingRouteShape: Shape {
    var startPoint: CGPoint
    var endPoint: CGPoint
    var elevation: Double

    @AnimatableIgnored
    var drawingDirection: Bool // Excluded from animation

    func path(in rect: CGRect) -> Path {
        // Drawing code
    }
}

Lines of code: 20 → 12 (40% reduction)

@AnimatableIgnored

Use @AnimatableIgnored to exclude properties from animation.

When to use

  • Debug values — Flags for development only
  • IDs — Identifiers that shouldn't animate
  • Timestamps — When the view was created/updated
  • Internal state — Non-visual bookkeeping
  • Non-VectorArithmetic types — Colors, strings, booleans

Example

@MainActor
@Animatable
struct ProgressView: View {
    var progress: Double // Animated
    var totalItems: Int // Animated (if Float, not if Int)

    @AnimatableIgnored
    var title: String // Not animated

    @AnimatableIgnored
    var startTime: Date // Not animated

    @AnimatableIgnored
    var debugEnabled: Bool // Not animated

    var body: some View {
        VStack {
            Text(title)
            ProgressBar(value: progress)
            if debugEnabled {
                Text("Started: \(startTime.formatted())")
            }
        }
    }
}

Real-World Use Case

@Animatable works for any numeric display — stock prices, heart rate, scores, timers, progress bars:

@MainActor
@Animatable
struct AnimatedValueView: View {
    var value: Double
    var changePercent: Double

    @AnimatableIgnored
    var label: String

    var body: some View {
        VStack(alignment: .trailing) {
            Text("\(value, format: .number.precision(.fractionLength(2)))")
                .font(.title)
            Text("\(changePercent > 0 ? "+" : "")\(changePercent, format: .percent)")
                .foregroundStyle(changePercent > 0 ? .green : .red)
        }
    }
}

// Usage
AnimatedValueView(value: currentPrice, changePercent: 0.025, label: "Price")
    .animation(.spring(duration: 0.8), value: currentPrice)

Part 4: Animation Types

Timing Curve Animations

Timing curve animations use bezier curves to control the speed of animation over time.

Built-in presets

.animation(.linear)          // Constant speed
.animation(.easeIn)          // Starts slow, ends fast
.animation(.easeOut)         // Starts fast, ends slow
.animation(.easeInOut)       // Slow start and end, fast middle

Custom timing curves

let customCurve = UnitCurve(
    startControlPoint: CGPoint(x: 0.2, y: 0),
    endControlPoint: CGPoint(x: 0.8, y: 1)
)

.animation(.timingCurve(customCurve, duration: 0.5))

Duration

All timing curve animations accept an optional duration:

.animation(.easeInOut(duration: 0.3))
.animation(.linear(duration: 1.0))

Default: 0.35 seconds

Spring Animations

Spring animations use physics simulation to create natural, organic motion.

Built-in presets

`


Content truncated.

axiom-ios-build

CharlesWiltgen

Use when ANY iOS build fails, test crashes, Xcode misbehaves, or environment issue occurs before debugging code. Covers build failures, compilation errors, dependency conflicts, simulator problems, environment-first diagnostics.

91

axiom-getting-started

CharlesWiltgen

Use when first installing Axiom, unsure which skill to use, want an overview of available skills, or need help finding the right skill for your situation — interactive onboarding that recommends skills based on your project and current focus

00

axiom-ui-testing

CharlesWiltgen

Use when writing UI tests, recording interactions, tests have race conditions, timing dependencies, inconsistent pass/fail behavior, or XCTest UI tests are flaky - covers Recording UI Automation (WWDC 2025), condition-based waiting, network conditioning, multi-factor testing, crash debugging, and accessibility-first testing patterns

00

axiom-core-spotlight-ref

CharlesWiltgen

Use when indexing app content for Spotlight search, using NSUserActivity for prediction/handoff, or choosing between CSSearchableItem and IndexedEntity - covers Core Spotlight framework and NSUserActivity integration for iOS 9+

00

axiom-vision-diag

CharlesWiltgen

subject not detected, hand pose missing landmarks, low confidence observations, Vision performance, coordinate conversion, VisionKit errors, observation nil, text not recognized, barcode not detected, DataScannerViewController not working, document scan issues

00

axiom-now-playing-carplay

CharlesWiltgen

CarPlay Now Playing integration patterns. Use when implementing CarPlay audio controls, CPNowPlayingTemplate customization, or debugging CarPlay-specific issues.

00

You might also like

flutter-development

aj-geddes

Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.

643969

drawio-diagrams-enhanced

jgtolentino

Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.

591705

ui-ux-pro-max

nextlevelbuilder

"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."

318398

godot

bfollington

This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.

339397

nano-banana-pro

garg-aayush

Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.

451339

fastapi-templates

wshobson

Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.

304231

Stay ahead of the MCP ecosystem

Get weekly updates on new skills and servers.