SwiftUI动画实现技能Skill swiftui-animation

本技能提供 SwiftUI 动画的全面指南,专注于高级动画、过渡效果、匹配几何和 Metal 着色器集成,适用于 iOS 和 macOS 应用开发。关键词:SwiftUI、动画、过渡、匹配几何、Metal 着色器、iOS、macOS、移动开发。

移动开发 0 次安装 0 次浏览 更新于 3/17/2026

名称: swiftui-animation 描述: 本技能提供在 SwiftUI 中实现高级动画、过渡、匹配几何效果和 Metal 着色器集成的全面指导。用于构建 iOS 和 macOS 应用中的动画、视图过渡、英雄动画或 GPU 加速效果。

SwiftUI 动画专家

为实施高级 SwiftUI 动画和 Metal 着色器集成的专家指导。涵盖动画曲线、弹簧效果、过渡、匹配几何效果、PhaseAnimator、KeyframeAnimator 和 GPU 加速着色器效果。

何时使用此技能

  • 理解运动设计原则以及何时使用动画
  • 使动画可访问且适合平台
  • 在 SwiftUI 中实现动画(弹簧、缓动、关键帧)
  • 创建视图过渡(淡入淡出、滑动、缩放、自定义)
  • 使用 matchedGeometryEffect 构建英雄动画
  • 通过 Metal 着色器添加 GPU 加速效果
  • 优化动画性能
  • 创建多阶段编排动画

快速参考

动画基础

// 显式动画(推荐)
withAnimation(.spring(response: 0.4, dampingFraction: 0.75)) {
    isExpanded.toggle()
}

// iOS 17+ 弹簧预设
withAnimation(.snappy) { ... }  // 快速,轻微弹跳
withAnimation(.smooth) { ... }  // 温和,无弹跳
withAnimation(.bouncy) { ... }  // 更多弹跳

常见过渡

// 基本
.transition(.opacity)
.transition(.scale)
.transition(.slide)
.transition(.move(edge: .bottom))

// 组合
.transition(.move(edge: .trailing).combined(with: .opacity))

// 非对称
.transition(.asymmetric(
    insertion: .move(edge: .bottom),
    removal: .opacity
))

匹配几何效果

@Namespace var namespace

// 源视图
ThumbnailView()
    .matchedGeometryEffect(id: "hero", in: namespace)

// 目标视图
DetailView()
    .matchedGeometryEffect(id: "hero", in: namespace)

Metal 着色器效果 (iOS 17+)

// 颜色操作
.colorEffect(ShaderLibrary.invert())

// 像素位移
.distortionEffect(
    ShaderLibrary.wave(.float(time)),
    maxSampleOffset: CGSize(width: 20, height: 20)
)

// 完整层访问
.layerEffect(ShaderLibrary.blur(.float(radius)), maxSampleOffset: .zero)

参考材料

详细文档可在 references/ 中找到:

  • motion-guidelines.md - HIG 运动设计原则

    • 目的驱动的运动哲学
    • 可访问性要求
    • 平台特定考虑(iOS、visionOS、watchOS)
    • 应避免的动画反模式
  • animations.md - 完整的动画 API 指南

    • 隐式与显式动画
    • 弹簧参数和预设
    • 动画修饰符(速度、延迟、重复)
    • PhaseAnimator 用于多步序列
    • KeyframeAnimator 用于属性特定时间线
    • 自定义可动画属性
  • transitions.md - 视图过渡指南

    • 内置过渡(透明度、缩放、滑动、移动)
    • 组合和非对称过渡
    • 匹配几何效果实施
    • 英雄动画模式
    • 内容过渡 (iOS 17+)
    • 自定义过渡创建
  • metal-shaders.md - GPU 着色器集成

    • SwiftUI 着色器修饰符 (colorEffect, distortionEffect, layerEffect)
    • 编写 Metal 着色器函数
    • 使用 UIViewRepresentable 嵌入 MTKView
    • 跨平台 Metal 集成(iOS/macOS)
    • 性能考虑

常见模式

可扩展卡片

struct ExpandableCard: View {
    @State private var isExpanded = false

    var body: some View {
        VStack {
            RoundedRectangle(cornerRadius: isExpanded ? 20 : 12)
                .fill(.blue)
                .frame(
                    width: isExpanded ? 300 : 150,
                    height: isExpanded ? 400 : 100
                )
        }
        .onTapGesture {
            withAnimation(.spring(response: 0.35, dampingFraction: 0.75)) {
                isExpanded.toggle()
            }
        }
    }
}

列表项出现

ForEach(Array(items.enumerated()), id: \.element.id) { index, item in
    ItemRow(item: item)
        .transition(.asymmetric(
            insertion: .move(edge: .trailing).combined(with: .opacity),
            removal: .move(edge: .leading).combined(with: .opacity)
        ))
        .animation(.spring().delay(Double(index) * 0.05), value: items)
}

脉动指示器

Circle()
    .fill(.blue)
    .frame(width: 20, height: 20)
    .scaleEffect(isPulsing ? 1.2 : 1.0)
    .opacity(isPulsing ? 0.6 : 1.0)
    .onAppear {
        withAnimation(.easeInOut(duration: 1.0).repeatForever(autoreverses: true)) {
            isPulsing = true
        }
    }

最佳实践

  1. 运动应有目的 - 不要为动画本身添加动画;支持体验而不掩盖它
  2. 使运动可选 - 补充触觉和音频;切勿将运动作为唯一的交流方式
  3. 力求简洁 - 简短、精确的动画感觉轻盈并有效传达信息
  4. 偏好显式动画 - 使用 withAnimation 而非 .animation() 修饰符以提高清晰度
  5. 使用弹簧动画 - 它们感觉更自然且原生 iOS
  6. .spring(response: 0.35, dampingFraction: 0.8) 开始 - 大多数交互的良好默认值
  7. 保持动画在 400 毫秒以下 - 更长感觉迟钝
  8. 让人们取消运动 - 不要强迫用户等待动画完成
  9. 在设备上测试 - 模拟器动画时间不同
  10. 分析着色器性能 - 对于复杂效果,GPU 时间很重要

故障排除

动画不工作

  • 确保状态变化包装在 withAnimation
  • 检查属性是否可动画
  • 验证视图是否实际变化

匹配几何跳跃

  • 两个视图必须使用相同的 ID 和命名空间
  • 切换时使用显式 withAnimation
  • 检查 zIndex 以正确分层

着色器不显示

  • 验证 .metal 文件已添加到目标
  • 检查着色器函数签名是否符合预期格式
  • 确保为失真效果正确设置 maxSampleOffset