动画交接
把 Figma Smart Animate / Lottie 规格翻译成代码中的 Framer Motion 或 CSS 动画。
为什么
动画是设计转代码交接最有损部分,因在 Figma 规为时间曲线和关键帧但在代码实现为字符串。设计师规'200ms ease-out 带 50ms stagger',开发者写'transition: 0.2s'——完全漏 easing 和 stagger。有纪律方法是在 token 系统定义运动 token(时长、easing、stagger),在 Figma 和代码都引用,复杂序列用 Framer Motion 因 CSS transition 表达不了编排。没有它, 动画感廉价不一致因每开发者选不同时间值。
何时使用
设计含非平凡运动(页面过渡、错列列表、弹簧物理)时。约 2-3 小时。静态设计可跳过。
如何做
1. 在 token 系统定义运动 token
- duration.fast: 150ms、duration.base: 250ms、duration.slow: 400ms
- easing.out: cubic-bezier(0, 0, 0.2, 1)、easing.spring: spring(1, 100, 10, 0)
2. Figma 里用 Smart Animate 并在画板名或注释文档化时间
- 画板名"Card hover — 200ms ease-out"
- 复杂路径动画(加载旋转、插画)导出 Lottie
3. 代码里编排序列用 Framer Motion,简单过渡用 CSS
- Framer Motion:布局动画、共享布局、拖拽、手势、错列
- CSS:hover、focus、简单 opacity/transform——无需 JS
4. 用 Framer Motion 的 staggerChildren 实现错列列表
- container variants:{ hidden: {}, show: { transition: { staggerChildren: 0.05 } } }
- item variants:{ hidden: { opacity: 0, y: 20 }, show: { opacity: 1, y: 0 } }
5. 尊重 prefers-reduced-motion:禁所有非必要动画
- Framer Motion:useReducedMotion() hook → 换即时过渡
- CSS:@media (prefers-reduced-motion: reduce) { * { transition: none !important } }示例
// 运动 token(tokens.json)
{ "motion": { "duration": { "fast": "150ms", "base": "250ms" }, "easing": { "out": [0, 0, 0.2, 1] } } }
// Framer Motion 错列列表
import { motion } from "framer-motion";
const container = { hidden: {}, show: { transition: { staggerChildren: 0.05 } } };
const item = { hidden: { opacity: 0, y: 20 }, show: { opacity: 1, y: 0, transition: { duration: 0.25, ease: [0, 0, 0.2, 1] } } };
export function List({ items }) {
return (
<motion.ul variants={container} initial="hidden" animate="show">
{items.map(i => <motion.li key={i.id} variants={item}>{i.label}</motion.li>)}
</motion.ul>
);
}
// 减少动画
import { useReducedMotion } from "framer-motion";
const reduce = useReducedMotion();
const transition = reduce ? { duration: 0 } : { duration: 0.25, ease: [0, 0, 0.2, 1] };常见问题
- ⚠一切用线性 easing,看起来机械——自然运动减速(ease-out)或过冲(spring)。
- ⚠UI 反馈动画超 300ms,感迟钝——用户感知 >100ms 为延迟。
- ⚠不尊重 prefers-reduced-motion,致前庭敏感用户运动病。
- ⚠动画布局属性(width、top)而非 transform,因布局触发回流致卡。
最佳实践
- ✓定义运动 token 并到处用——永不硬编码时长或 easing 在组件里。
- ✓动画优先 transform 和 opacity——GPU 加速不触发回流。
- ✓共享元素过渡(列表→详情)用 Framer Motion 的 layout prop——它替你处理 FLIP 技术。
- ✓启用 prefers-reduced-motion: reduce 测试确保无动画应用可用。