网页动效
好的网页动效首先是设计决策,其次才是库调用。请按以下工作流顺序操作;仅在需要某个步骤时才加载对应的规则文件。
工作流
1. 在做出选择前先阅读项目
- 检查
package.json。如果已经安装了动效库,请使用它。 不要为了单一效果而添加第二个库。 - 注意所用框架(React / Next.js App Router / Vue / Svelte / 纯HTML),并确认组件是否在服务端渲染(在Next.js中客户端动效需要
"use client")。 - 检查CSS变量或主题文件中是否存在已有的动效令牌(时长、缓动函数),并复用它们。
2. 确定动效的目的
每个动效都需要一个任务。为每个元素选择一个:
| 任务 | 示例 | 典型时长预算 |
|---|---|---|
| 反馈 — 确认一个操作 | 按钮按下、切换、复制到剪贴板 | 100–200ms |
| 定位 — 显示某物从何而来或去了何处 | 模态框从其触发元素打开、列表项重新排序、路由变化 | 200–400ms |
| 吸引注意 — 指向一个事物 | 单个首屏序列、新通知 | 400–1200ms,一次 |
| 叙事 — 讲述与滚动相关的故事 | 固定的产品导览、擦洗的时间线 | 与滚动距离绑定 |
如果一个元素没有任务,就不要对它做动画。一个精心编排的瞬间胜过每个区块都做一个淡入效果。阅读 rules/motion-design.md 以了解时长、缓动、编排和“高级感”检查清单。
3. 选择能完成任务的最轻量工具
优先考虑平台,然后才是库:
| 需求 | 使用 | 规则文件 |
|---|---|---|
| 悬停、聚焦、按压、简单循环 | CSS 过渡 / @keyframes | css-keyframes.md |
| 对话框、弹出框、下拉菜单的进入和退出 | CSS @starting-style + transition-behavior: allow-discrete | css-keyframes.md |
| 页面/路由过渡、状态间的共享元素变形 | View Transitions API | view-transitions.md |
| 简单的滚动关联展现、进度条、视差 | CSS animation-timeline: view() / scroll() | scroll-animations.md |
| 固定区块、擦洗的多步骤时间线、水平滚动 | GSAP + ScrollTrigger | gsap.md |
| 分割文本/行遮罩标题展现 | GSAP SplitText | gsap.md |
| React 进入/退出、布局和共享布局动画、手势 | Motion for React (motion/react) | framer-motion.md |
| 无框架的命令式动画、弹簧 | Motion (motion) | motion-one.md |
| 不使用GSAP的SVG线条绘制和变形 | Anime.js v4 (svg.createDrawable, svg.morphTo) | animejs.md |
| 不相关形状之间的复杂路径变形 | Flubber (或 GSAP MorphSVG) | flubber.md |
| After Effects 动画播放 | Lottie (dotLottie) | lottie.md |
| 交互式、状态驱动的插画动画 | Rive | rive.md |
| 动画图表 | D3 过渡 | d3.md |
| 大量交互式 2D 形状(编辑器、图表) | Konva | konva.md |
| 3D、粒子、着色器 | Three.js / React Three Fiber | three-js.md |
当选择不明确时,请阅读 rules/choosing-library.md。
4. 遵循不可协商的原则进行构建
以下原则适用于每个动画,无论使用哪个库:
- 动画
transform和opacity。 避免动画width、height、top、left、margin;使用scale/translate、FLIP(GSAP Flip、Motionlayout)或 View Transitions 来处理布局变化。参见 rules/performance.md。 - 尊重
prefers-reduced-motion。 将移动替换为淡入或瞬间变化;切勿直接删除内容的入场动画导致其保持不可见。滚动擦洗效果应变为静态。 - 切勿在 JS 运行前隐藏内容。 在 JS 中(或通过
.js类)设置初始隐藏状态,以便在脚本失败时内容仍然可见。在使用 SSR 时,通过在首次绘制前应用初始样式,避免先可见后隐藏的内容闪烁。 - 清理动画。 在组件卸载时还原或销毁动画(使用
useGSAP、createScope().revert()、gsap.context),并在路由变化时销毁 ScrollTrigger。 - 保持交互响应性。 任何用户触发的动画都应可中断:第二次点击不能排队等待第一次完成。切勿为等待动画完成而阻止输入。
- 不要将焦点动效带走。 移动的元素必须保持可见的
:focus-visible状态,动画化对话框也必须正确移动焦点。
5. 在真实浏览器中验证
不要仅仅通过阅读代码就报告动画已完成。运行它并检查:
- 动画已播放,最终状态与设计一致(截取动画中和静止状态截图)。
- 没有控制台错误,动画开始时没有布局偏移。
- 模拟
prefers-reduced-motion: reduce并确认缩减版本正常工作且内容可见。 - 调整到移动宽度:固定区块和分割文本仍然有效(在调整大小时重新分割)。
- 滚动驱动效果在向上和向下滚动时都正常工作,并且在页面中间重新加载后也正常。
- 性能面板:动画期间没有长帧,没有因为动画属性导致的布局/绘制尖峰。
最小起始点
// GSAP + ScrollTrigger (npm i gsap)
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
gsap.from(".card", {
y: 40, opacity: 0, duration: 0.8, ease: "expo.out", stagger: 0.08,
scrollTrigger: { trigger: ".cards", start: "top 80%" },
});
// Motion for React (npm i motion)
import { motion, AnimatePresence } from "motion/react";
<AnimatePresence>
{open && (
<motion.div
key="panel"
initial={{ opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 8 }}
transition={{ type: "spring", duration: 0.35, bounce: 0 }}
/>
)}
</AnimatePresence>
/* 纯平台滚动展现:Chrome 115+, Safari 26+, Firefox 159+ */
@media (prefers-reduced-motion: no-preference) {
@supports (animation-timeline: view()) {
.reveal {
animation: reveal linear both;
animation-timeline: view();
animation-range: entry 10% cover 30%;
}
}
}
@keyframes reveal { from { opacity: 0; translate: 0 2rem; } }
规则文件
- rules/motion-design.md — 时长、缓动、编排、什么让动效感觉高级
- rules/choosing-library.md — 决策流程、能力矩阵、打包大小
- rules/performance.md — 仅合成器属性、性能分析、
will-change、减少运动 - rules/scroll-animations.md — CSS 滚动时间线、ScrollTrigger 模式、平滑滚动
- rules/view-transitions.md — 同文档和跨文档页面过渡
- rules/css-keyframes.md — 过渡、
@keyframes、@starting-style、linear()缓动 - rules/gsap.md — 时间线、ScrollTrigger、SplitText、Flip、
useGSAP - rules/framer-motion.md — Motion for React:变体、
AnimatePresence、布局、手势 - rules/motion-one.md — Motion 原生 JS:
animate、序列、scroll、inView - rules/animejs.md — Anime.js v4:时间线、交错、SVG 绘制和变形
- rules/lottie.md — dotLottie 播放器、控件、事件
- rules/rive.md — 状态机和输入
- rules/d3.md — 数据连接过渡
- rules/flubber.md — 路径变形
- rules/konva.md — Canvas 2D 形状和补间
- rules/three-js.md — 场景、R3F、性能
这些技术的可工作示例位于 demos/ 目录中。