关于 emilkowal-animations-swift
面向 Apple 平台界面的 SwiftUI 和 AppKit 动画参考技能,包含分为 10 类的 86 条规则。它提供代码评审指南、实现参数参考,以及 Web 概念到 SwiftUI 的映射。
主要功能
- 01涵盖 10 类的 86 条规则
- 02动画代码评审清单
- 03时长与缓动曲线指南
- 04手势、转场和滚动模式
- 05无障碍与性能建议
- 06Web 到 SwiftUI 的概念映射
适用场景
- 01评审 SwiftUI 动画实现
- 02为界面转场选择时长
- 03构建手势驱动的动效与导航
- 04检查动画的无障碍性和性能
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ pluk-inc/ skills --skill emilkowal-animations-swift安装后在 Claude Code 中输入/emilkowal-animations-swift确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
metadata.jsonassets/templates/_template.mdreferences/_sections.mdappkit-animator-proxy.mdappkit-core-animation.mdappkit-implicit-animations.mdappkit-layer-backed-views.mdappkit-nsanimation-context.mdappkit-spring-animation.mdease-avoid-linear.mdease-custom-timing-curve.mdease-ease-in-for-exits.mdease-ease-inout-for-emphasis.mdease-match-context.mdease-prefer-easeout.mdease-spring-damping.mdease-spring-default.mdease-spring-ios17.mdease-spring-response.mdgesture-asymmetric-press-release.mdgesture-cancellation.mdgesture-drag-basic.mdgesture-drag-constraints.mdgesture-drag-velocity.mdgesture-gesture-state.mdgesture-hover-macos.mdgesture-long-press.mdgesture-magnify-gesture.mdgesture-rotation-gesture.mdgesture-sensory-feedback.md详细介绍
SwiftUI 与 AppKit 动画最佳实践
面向 Apple 平台界面的全面动画指南,改编自 Emil Kowalski 的 Web 动画原则和 Framer Motion 最佳实践。包含 10 个类别中的 86 条规则,针对 iOS 17+,并按影响程度排序。
审查格式(必需)
审查 UI 动画代码时,必须使用包含“修改前/修改后/原因”列的 Markdown 表格。不要使用将“修改前:”和“修改后:”分成多行的列表。始终输出如下所示的实际 Markdown 表格:
| 修改前 | 修改后 | 原因 |
|---|---|---|
.animation(.default) | .animation(.easeOut(duration: 0.2)) | 明确指定缓动曲线;避免使用默认值 |
scaleEffect(0) | scaleEffect(0.95) with .opacity(0) | 现实世界中没有东西会凭空出现 |
.easeIn on dropdown | .easeOut(duration: 0.2) | easeIn 显得迟缓;easeOut 能提供即时反馈 |
| No press feedback on button | scaleEffect(isPressed ? 0.97 : 1.0) | 按钮必须能对按压操作做出响应 |
.scaleEffect(anchor: .center) on popover | .scaleEffect(anchor: .top) matching trigger | 弹出框应从触发位置缩放,而不是从中心缩放 |
每个发现的问题占一行。“原因”列简要说明理由。
审查清单
审查 SwiftUI 动画代码时,请检查以下问题:
| 问题 | 修复方法 |
|---|---|
.animation(.default) 或未明确指定曲线 | 指定精确的缓动方式:.easeOut(duration: 0.2) 或 .spring(duration: 0.3) |
使用 scaleEffect(0) 的入场动画 | 从 scaleEffect(0.95) 开始,并添加 .opacity(0) |
进入 UI 元素时使用 .easeIn | 改用 .easeOut 或 .spring() |
弹出框使用 .scaleEffect(anchor: .center) | 将锚点设为与触发位置一致(模态框除外) |
| 由键盘触发的操作使用动画 | 完全移除动画——改用即时状态变化 |
| UI 元素的动画时长 > 300ms | 缩短至 150-250ms,或使用 spring |
悬停动画没有 #if os(macOS) 保护 | 添加平台检查,或检查 .onHover 是否可用 |
withAnimation 包裹高频操作 | 移除——每天触发 100 次以上的操作应即时响应 |
对 .frame() 或 .padding() 添加动画 | 改用 .scaleEffect、.offset、.opacity(由 GPU 加速) |
| 入场和退出使用相同的转场速度 | 加快退出速度:.asymmetric(insertion: 0.3s, removal: 0.15s) |
| 所有元素同时出现 | 添加错开延迟(项目之间间隔 30-80ms) |
使用手动 Timer/CADisplayLink 动画循环 | 改用 .animation() 或 withAnimation(在渲染服务器上运行) |
未检查 accessibilityReduceMotion | 添加 @Environment(\.accessibilityReduceMotion) 检查 |
| 可点击元素没有按压反馈 | 通过 ButtonStyle 在按压时添加 scaleEffect(0.97) |
适用场景
在以下情况中参考这些指南:
- 为 SwiftUI 视图添加动画
- 选择缓动曲线、弹簧效果或时间参数
- 实现基于手势的交互(拖动、轻点、长按)
- 构建转场和导航动画
- 使用
matchedGeometryEffect实现共享元素转场 - 创建与滚动联动的效果或视差效果
- 使用 iOS 17+ 的
PhaseAnimator或KeyframeAnimator - 优化动画性能
- 通过
accessibilityReduceMotion确保动画的无障碍支持 - 编写 AppKit/macOS 专用动画
按优先级划分的规则类别
| 优先级 | 类别 | 影响 | 前缀 |
|---|---|---|---|
| 1 | 时间曲线与缓动 | 严重 | ease- |
| 2 | 时长与时间 | 严重 | timing- |
| 3 | 动画属性 | 高 | props- |
| 4 | 变换与效果 | 高 | transform- |
| 5 | 手势与交互 | 高 | gesture- |
| 6 | 转场与导航 | 中高 | transition- |
| 7 | 滚动与视差 | 中 | scroll- |
| 8 | 策略性动画 | 中 | strategy- |
| 9 | 无障碍与润色 | 中 | polish- |
| 10 | AppKit 专用 | 低至中 | appkit- |
快速参考
1. 时间曲线与缓动(关键)
ease-prefer-easeout- 默认使用 easeOut 缓动ease-avoid-linear- 避免在 UI 动画中使用线性缓动ease-spring-default- 优先使用弹簧效果,实现自然运动ease-spring-ios17- 使用带有弹跳和持续时间参数的 iOS 17 Spring 结构体ease-custom-timing-curve- 使用 timingCurve 创建自定义曲线ease-ease-in-for-exits- 退出动画使用 easeInease-ease-inout-for-emphasis- 强调性运动使用 easeInOutease-spring-response- 配置弹簧响应,以控制时长感ease-spring-damping- 配置弹簧阻尼,以控制弹跳效果ease-match-context- 根据动画场景选择匹配的缓动
2. 持续时间与时序(关键)
timing-200ms-default- 将 200ms 作为 UI 动画的默认时长timing-100ms-micro- 微交互使用 100ms 时长timing-300ms-emphasis- 强调性动画时长控制在 300ms 以内timing-stagger-children- 错开子项动画,以协调动画编排timing-delay-strategic- 策略性地使用延迟来安排动画顺序
3. 动画属性(高优先级)
props-opacity-scale- 优先使用透明度和缩放,以提升性能props-avoid-size-animate- 避免直接对视图框架尺寸进行动画处理props-transform-origin- 为变换设置锚点props-drawing-group- 对复杂层级使用 drawingGroupprops-animation-disable- 使用 animation(nil) 禁用动画props-explicit-animation- 使用 withAnimation 进行显式控制props-implicit-animation- 使用 .animation 修饰符实现隐式动画
4. 变换与效果(高优先级)
transform-scale-subtle- 使用适度的缩放值(0.95-0.98)transform-rotation-purposeful- 有目的地应用旋转transform-translate-direction- 沿有意义的方向平移transform-3d-perspective- 使用 rotation3DEffect 增加深度感transform-order-matters- 修饰符顺序会影响输出效果transform-anchor-point- 设置旋转或缩放的原点锚点transform-combine-effects- 有目的地组合变换效果transform-blur-crossfade- 使用模糊效果掩盖不完美的交叉淡入淡出
5. 手势与交互(高)
gesture-tap-feedback- 提供即时点击反馈gesture-long-press- 为长按状态添加动画gesture-drag-basic- 实现流畅的拖动交互gesture-drag-constraints- 将拖动限制在边界内gesture-drag-velocity- 利用速度实现惯性效果gesture-gesture-state- 使用 @GestureState 存储临时值gesture-updating-modifier- 使用 .updating 提供实时反馈gesture-simultaneous-vs-exclusive- 选择手势组合方式gesture-magnify-gesture- 实现捏合缩放gesture-rotation-gesture- 实现旋转手势gesture-hover-macos- 处理 macOS 上的悬停gesture-sensory-feedback- 为手势搭配触觉反馈gesture-spring-on-release- 在手势结束时弹回gesture-cancellation- 妥善处理手势取消gesture-asymmetric-press-release- 采用不对称的按下/释放时长
6. 转场与导航(中高)
transition-builtin-types- 使用内置转场类型transition-asymmetric- 使用不对称转场区分进入和退出效果transition-combined- 组合转场以实现更丰富的效果transition-custom-modifier- 创建自定义转场修饰符transition-matched-geometry- 正确使用 matchedGeometryEffecttransition-namespace-scope- 管理 @Namespace 生命周期transition-navigation-transitions- 自定义导航转场transition-sheet-presentations- 为工作表呈现添加动画transition-id-for-replacement- 使用 .id() 替换视图transition-content-transition- 对文本使用 contentTransition
7. 滚动与视差(中)
scroll-geometry-reader- 使用 GeometryReader 获取滚动位置scroll-preference-key- 使用 PreferenceKey 获取滚动数据scroll-parallax-effect- 创建视差滚动效果scroll-sticky-header- 实现带动画的粘性标题scroll-scroll-transition- 使用 iOS 17 的 scrollTransition 修饰符scroll-visual-effect- 使用 iOS 17 的 visualEffect 修饰符
8. 策略性动画(中)
strategy-purposeful-motion- 每个动画都需要明确目的strategy-hierarchy-emphasis- 使用动态效果体现层级strategy-state-communication- 清晰地呈现状态变化strategy-spatial-continuity- 保持空间关系strategy-brand-expression- 通过动态效果展现品牌strategy-frequency-framework- 先根据使用频率做判断,再添加动画strategy-no-keyboard-animation- 绝不为键盘触发的操作添加动画strategy-component-design- 受欢迎的库所遵循的组件设计原则
9. 无障碍与润色(中)
polish-reduce-motion- 尊重 accessibilityReduceMotionpolish-phase-animator- 使用 PhaseAnimator 编排序列动画polish-keyframe-animator- 使用 KeyframeAnimator 实现复杂路径polish-animation-completions- 处理动画完成事件polish-interruptible-animations- 使动画可中断polish-animation-debugging- 高效调试动画polish-performance-profiling- 分析动画性能polish-symbol-effects- 使用 SF Symbol 效果polish-text-animations- 使用 contentTransition 为文本添加动画polish-haptic-pairing- 将动画与触觉反馈配合使用polish-skip-subsequent-delays- 后续工具提示/弹出框跳过延迟
10. AppKit 特定内容(低至中)
appkit-nsanimation-context- 使用 NSAnimationContext 对动画进行分组appkit-core-animation- 使用 Core Animation 图层appkit-layer-backed-views- 启用图层支持以提升性能appkit-implicit-animations- 利用隐式图层动画appkit-spring-animation- 在 AppKit 中创建弹簧动画appkit-animator-proxy- 使用 animator 代理为视图添加动画
关键值参考
| 值 | 用法 |
|---|---|
.spring(duration: 0.3, bounce: 0.2) | 标准 iOS 17 弹簧动画 |
.spring(response: 0.3, dampingFraction: 0.7) | 经典弹簧配置 |
.easeOut(duration: 0.2) | 标准 UI 转场 |
scaleEffect(0.97) | 按钮按下反馈 |
scaleEffect(0.95) | 最小进入缩放值(绝不缩放至 0) |
0.2 秒 | 默认微交互时长 |
0.3 秒 | UI 动画的最长时长 |
0.5 秒 | Sheet/抽屉动画时长 |
概念映射(Web 到 SwiftUI)
| Web 概念 | SwiftUI 对应项 |
|---|---|
ease-out | .easeOut 或 Animation.easeOut(duration:) |
cubic-bezier(a,b,c,d) | .timingCurve(a, b, c, d, duration:) |
| Framer Motion spring | .spring(duration:bounce:)(iOS 17+) |
transform: scale(0.97) | .scaleEffect(0.97) |
transform-origin | .scaleEffect(anchor: .topLeading) |
useMotionValue | @State / @GestureState |
AnimatePresence | .transition() + .id() |
layoutId | .matchedGeometryEffect(id:in:) |
useScroll | GeometryReader + PreferenceKey |
whileHover/whileTap | .onHover {} / 手势修饰符 |
dragConstraints | 使用 onChange 边界的 DragGesture |
prefers-reduced-motion | @Environment(\.accessibilityReduceMotion) |
参考文件
| 文件 | 描述 |
|---|---|
| references/_sections.md | 分类定义和排序 |
| assets/templates/_template.md | 新规则模板 |
| metadata.json | 版本和参考信息 |
评论
支持 Markdown