动画系统架构师 是做什么的?
使用Framer Motion、GSAP、View Transitions API和弹性物理引擎构建高性能、可访问的动画系统,打造流畅的UI体验。
激活触发器
激活场景:页面过渡、布局动画、滚动触发动画、微交互、弹性物理、motion.div、gsap.to、View Transition API、共享元素过渡、交错列表动画。
不适用场景:纯CSS悬停/焦点效果——请使用css-in-js-architect。Canvas/WebGL渲染——请使用creative-coding-expert。Lottie文件播放——请使用标准Lottie集成。
快速入门
- 选择引擎——React声明式选用Framer Motion,时间线密集型或非React项目选用GSAP,跨页面导航选用View Transitions API。
- 仅对变换和透明度进行动画——这些操作在合成器线程(GPU)上运行,可避免布局抖动。
- 谨慎使用
will-change——仅对即将动画的元素应用,动画完成后移除。 - 尊重
prefers-reduced-motion——对于有此类请求的用户,禁用或简化所有动画。 - 使用开发者工具进行性能分析——在Performance面板中检查动画期间是否有布局偏移。
核心能力
| 领域 | 技术 | 关键模式 |
|---|---|---|
| 声明式React | Framer Motion 11+, motion组件 | 布局动画、AnimatePresence、变体 |
| 时间线动画 | GSAP 3.12+, ScrollTrigger | 滚动驱动序列、固定、擦洗 |
| 页面过渡 | View Transitions API, Next.js useViewTransition | 跨页面共享元素过渡 |
| 弹性物理 | Framer Motion弹性, react-spring | 自然缓动、可中断动画 |
| 微交互 | CSS过渡 + Framer Motion | 按钮反馈、悬停状态、加载指示器 |
| 滚动驱动 | CSS animation-timeline: scroll(), GSAP ScrollTrigger | 视差、进度指示器、滚动时显示 |
架构模式
模式1:Framer Motion布局动画
import { motion, AnimatePresence, LayoutGroup } from 'framer-motion';
function FilterableGrid({ items, filter }: Props) {
const filtered = items.filter(item => item.category === filter);
return (
<LayoutGroup>
<motion.div layout className="grid grid-cols-3 gap-4">
<AnimatePresence mode="popLayout">
{filtered.map(item => (
<motion.div
key={item.id}
layout // 对位置变化进行动画
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ type: 'spring', stiffness: 300, damping: 25 }}
>
<Card item={item} />
</motion.div>
))}
</AnimatePresence>
</motion.div>
</LayoutGroup>
);
}
模式2:View Transitions API用于页面导航
// app/components/TransitionLink.tsx
'use client';
import { useRouter } from 'next/navigation';
import { useCallback } from 'react';
export function TransitionLink({ href, children }: { href: string; children: React.ReactNode }) {
const router = useRouter();
const handleClick = useCallback((e: React.MouseEvent) => {
e.preventDefault();
if (!document.startViewTransition) {
router.push(href);
return;
}
document.startViewTransition(() => {
router.push(href);
});
}, [href, router]);
return <a href={href} onClick={handleClick}>{children}</a>;
}
/* 通过 view-transition-name 实现共享元素过渡 */
.product-image {
view-transition-name: product-hero;
}
::view-transition-old(product-hero) {
animation: fade-and-scale 0.3s ease-out;
}
::view-transition-new(product-hero) {
animation: fade-and-scale 0.3s ease-in reverse;
}
模式3:减少运动偏好处理
import { useReducedMotion } from 'framer-motion';
function AnimatedComponent() {
const shouldReduce = useReducedMotion();
return (
<motion.div
initial={{ opacity: 0, y: shouldReduce ? 0 : 20 }}
animate={{ opacity: 1, y: 0 }}
transition={shouldReduce
? { duration: 0 }
: { type: 'spring', stiffness: 260, damping: 20 }
}
>
内容
</motion.div>
);
}
┌─ 动画决策树 ──────────────────────────────────┐
│ │
│ prefers-reduced-motion? │
│ ├── 是 → 仅即时透明度淡入(无运动) │
│ └── 否 → 完整弹性/变换动画 │
│ │
│ 什么是正在动画的元素? │
│ ├── transform/opacity → GPU合成器(好) │
│ ├── width/height → 布局抖动(避免) │
│ └── box-shadow → 仅绘制(可接受) │
└───────────────────────────────────────────────────┘
反模式
- 对
width、height、top、left进行动画——每帧触发布局重新计算。使用transform: translate/scale替代以获得60fps。 - 在每个元素上使用
will-change——向GPU提升过多图层,增加内存使用。仅对即将动画的元素应用。 - 忽略
prefers-reduced-motion——对运动敏感的用户会出现恶心或癫痫症状。务必检查并尊重此媒体查询。 - 微交互动画持续时间 > 500ms——使UI感觉迟钝。按钮/悬停反馈保持在200ms以下,页面过渡保持在400ms以下。
- 在滚动过程中不使用
requestAnimationFrame或ScrollTrigger进行动画——导致卡顿。使用GSAP ScrollTrigger或CSSanimation-timeline: scroll()进行滚动驱动动画。
质量检查清单
- 所有动画均使用
transform和opacity(合成器友好属性) - 通过
useReducedMotion或CSS媒体查询尊重prefers-reduced-motion - 微交互在200ms以下,页面过渡在400ms以下
- 使用
AnimatePresence处理挂载/卸载动画 - 布局动画使用Framer Motion的
layout属性(而非手动位置计算) -
will-change仅在动画期间应用,动画完成后移除 - Chrome DevTools Performance面板中无卡顿(无超过16ms的长帧)
- 动画是可中断的(弹性物理,而非固定关键帧配合
ease) - View Transitions API有针对不支持浏览器的降级方案
- 滚动驱动动画使用
animation-timeline或ScrollTrigger(而非滚动事件监听器)