2026-10-07 16:06:27 +08:00
|
|
|
|
# 动效
|
|
|
|
|
|
|
|
|
|
|
|
## 每个界面先做三处动效
|
|
|
|
|
|
|
2026-10-14 10:21:46 +08:00
|
|
|
|
完全不动的界面像一张截图:按下没有回应,切换没有来路,用户只能猜刚才发生了什么。新界面和改动了操作流程的界面,先把这三处做出来,手感写进方向卡的“动效”一栏,改流程和加新功能时写进方案卡或设计说明:
|
2026-10-07 16:06:27 +08:00
|
|
|
|
|
|
|
|
|
|
1. **主操作的反馈。** 按下立刻有回应,完成时交出一个结果:按钮陷下去再弹回,勾号画出来,数字滚到新值。
|
|
|
|
|
|
2. **一处状态切换的来路。** 选中、展开、换视图、增删列表项时,让人看见东西从哪里来、到哪里去,见下文“界面过渡”。
|
|
|
|
|
|
3. **第一次进入时的一次出场。** 主角先到,其余按阅读顺序跟上,只在首次进入时播放。
|
|
|
|
|
|
|
2026-10-14 10:21:46 +08:00
|
|
|
|
这三处之外再加的动效,每个都要承担反馈、引导、连续或品牌表达中的一项;滚动淡入、视差、跟随鼠标和装饰性循环最容易变成干扰。
|
2026-10-07 16:06:27 +08:00
|
|
|
|
|
|
|
|
|
|
| 目的 | 适合考虑的方式 |
|
|
|
|
|
|
| --- | --- |
|
2026-10-14 10:21:46 +08:00
|
|
|
|
| 按下、聚焦、展开或普通的状态变化 | 用浏览器原生的过渡,或已有组件自带的小过渡 |
|
2026-10-07 16:06:27 +08:00
|
|
|
|
| 视图之间的切换、元素换位置 | 共享元素过渡,见下文“界面过渡” |
|
2026-10-14 10:21:46 +08:00
|
|
|
|
| 拖拽、手势、位置和大小的变化、多个元素配合的动画 | 用项目里已有的成熟动效库 |
|
|
|
|
|
|
| 特殊品牌画面、材质、复杂物理效果 | 图片、3D、着色器或预渲染视频,按需求取舍;什么时候用实时 3D 见 [素材](media.md) |
|
|
|
|
|
|
| 用鼠标、触控或滚动控制一段叙事的进度 | 让动画的进度直接跟着输入走,往回滚和快速操作都要处理好;见 [滚动叙事](scroll-narrative.md) |
|
2026-10-07 16:06:27 +08:00
|
|
|
|
|
2026-10-14 10:21:46 +08:00
|
|
|
|
需要精确控制状态的界面,用代码写动画;画面怎么变早就定好的,可以用生成的视频。要显示实时数据、要让人真的去操作的控件,不能用视频代替。
|
2026-10-07 16:06:27 +08:00
|
|
|
|
|
|
|
|
|
|
## 手感
|
|
|
|
|
|
|
|
|
|
|
|
动效的手感从方向的材质和调性推出,用“动作 + 实物”来命名和选参数(弹簧刚度 / 阻尼):
|
|
|
|
|
|
|
|
|
|
|
|
| 动作 | 实物参照 | 刚度 / 阻尼 | 适合 |
|
|
|
|
|
|
| --- | --- | --- | --- |
|
|
|
|
|
|
| 咔嗒 | 磁铁吸合、卡扣、拨动开关 | 350–400 / 10–15 | 按钮、开关、下拉展开 |
|
|
|
|
|
|
| 滑入 | 气压闭门器、抽屉阻尼 | 250–300 / 20–25 | 底部面板、抽屉、折叠 |
|
|
|
|
|
|
| 流淌 | 倒蜂蜜、雾气弥散 | 150–200 / 30–40 | 页面转场、主视觉出现 |
|
|
|
|
|
|
| 砸落 | 锤击、重物落桌 | 400–500 / 5–10 | 确认选择、完成反馈 |
|
|
|
|
|
|
| 回弹 | 橡皮球、蹦床 | 300 / 8 | 庆祝提示、儿童与游戏 |
|
|
|
|
|
|
| 漂浮 | 氦气球、飘絮 | 100 / 25 | 冥想、梦幻场景、空闲循环 |
|
|
|
|
|
|
|
|
|
|
|
|
重的材质(石、金属、陶)偏咔嗒和砸落,轻的材质(纸、布、雾)偏漂浮和流淌;高频操作用短促的动作,少见的品牌时刻才用绵长的。喧闹粗粝的方向可以用硬切、80–150ms 的线性跳变和抽帧,作为有意的品牌表达;被禁止的只是没有考虑过的默认缓动。
|
|
|
|
|
|
|
|
|
|
|
|
过冲幅度跟着面积走。整页、面板这类大面积的东西,过冲不超过 1–2%,否则整块画面会晃;徽章、勾选标记这类小东西可以过冲 10–20%,显得有弹性。表里阻尼偏低的参数只用在小物件上。
|
|
|
|
|
|
|
|
|
|
|
|
网页可以把弹簧写成缓动曲线:按刚度和阻尼对位移做数值积分,取 20–30 个采样点写进 `linear()`,时长取位移稳定在终点 0.5% 以内的时刻。不支持的浏览器退回相近的 `cubic-bezier`。
|
|
|
|
|
|
|
|
|
|
|
|
## 呼应:让动作彼此接上
|
|
|
|
|
|
|
2026-10-14 10:21:46 +08:00
|
|
|
|
一个动作引起的变化沿同一条路传下去,前一段的终点是下一段的起点;不要按钮、面板和数字各动各的。
|
2026-10-07 16:06:27 +08:00
|
|
|
|
|
|
|
|
|
|
- **从被操作的地方出发。** 点“加入购物袋”,商品缩成一个点飞进袋子,袋子上的数字跟着跳一下;删掉一行,它朝删除按钮的方向收走,下面的行补上来。
|
|
|
|
|
|
- **一次切换朝一个方向。** 卡片往左滑,标题、序号和底色也往左换;数字往上滚,进度也往上涨。方向一乱,就成了几段互不相干的动画。
|
|
|
|
|
|
- **主角先动,其余被带动。** 被影响的东西晚 40–80ms 跟上,幅度更小,像被主角拉过去的。全部同时起跑、同样幅度,看起来只是一起闪了一下。
|
|
|
|
|
|
- **形状接力。** 上一个状态里的元素变成下一个状态里的元素:按钮展开成面板,搜索图标拉长成输入框,播放键变成暂停键。用户一眼看出它们是同一个东西。
|
2026-10-14 10:21:46 +08:00
|
|
|
|
- **动法和画面是同一种材质。** 动作的轻重、停顿和回弹从方向卡的生成引擎和控件语法推出。
|
2026-10-07 16:06:27 +08:00
|
|
|
|
|
|
|
|
|
|
### 巧思从产品里找
|
|
|
|
|
|
|
2026-10-14 10:21:46 +08:00
|
|
|
|
巧思是让一处动效讲出这个产品自己的事,不是加更多花样。写成一句:这个产品里的哪样东西,因为用户的哪个动作,发生了只有它才会有的变化。
|
2026-10-07 16:06:27 +08:00
|
|
|
|
|
|
|
|
|
|
找不到这样的动作,就把三处基本动效做准,不硬造。一页最多一两处巧思,其余动效安静、短促。
|
|
|
|
|
|
|
|
|
|
|
|
## 界面过渡
|
|
|
|
|
|
|
|
|
|
|
|
**连续。** 用户点的东西就是下一屏的主角。从列表进入详情,被点的那一项放大成详情,其他项淡出;返回时它缩回原位,页面回到原来的滚动位置。原位已经不在视口里,就先把它滚到可见,再缩回去。
|
|
|
|
|
|
|
|
|
|
|
|
**方向一致。** 下一项从右边进,上一项从左边进;打开和关闭互为逆过程;侧面板从它所在的那一侧滑入滑出。方向随意的动画比没有动画更让人迷惑。
|
|
|
|
|
|
|
|
|
|
|
|
**只变形状时不做交叉淡化。** 切换视口、筛选、展开说明、缩放,这类变化里内容还是同一个东西,只是尺寸和位置变了。让外框直接变形,内容立即显示新状态。交叉淡化会让新旧两张缩放不同的画面叠在一起,出现重影。只有内容本身换了,才淡入淡出。
|
|
|
|
|
|
|
|
|
|
|
|
**离开、加入、留下分开处理。** 被移除的淡出,新加入的淡入,留下的滑到新位置。三者用同一种淡化,列表就会整片闪烁。
|
|
|
|
|
|
|
|
|
|
|
|
**选中指示用一块会移动的滑块。** 分段控件、标签页、列表当前项,都用同一块底板滑到新位置,而不是旧的熄灭、新的点亮。选项宽度不同时,宽度一起过渡。首次显示、窗口缩放和字体加载完成后直接放到位,不要从 0 宽度长出来。
|
|
|
|
|
|
|
|
|
|
|
|
**先准备好目的地。** 目的地要加载的内容,例如图片或内嵌页面,先加载或预先渲染好,否则动画会停在一块白屏上。需要来回切换的视图预先渲染并留在页面里,切换时只移动,不重新加载。内容加载完成后再淡入,不先闪一下白底。
|
|
|
|
|
|
|
|
|
|
|
|
**离开比进入快。** 退出时长约为进入的 60–70%,用加速曲线;进入用减速曲线或弹簧。
|
|
|
|
|
|
|
|
|
|
|
|
**到头要有反馈。** 已经是第一项或最后一项时,轻轻顶一下(往返 10–15px),而不是毫无反应。
|
|
|
|
|
|
|
2026-10-14 10:21:46 +08:00
|
|
|
|
### 整页转场的稳定性取舍
|
|
|
|
|
|
|
|
|
|
|
|
整页切换和组件的过渡不一样:旧页面要卸载,新页面要挂载。按稳不稳、难不难做,分三类:
|
|
|
|
|
|
|
|
|
|
|
|
- **遮罩式(Curtain / Wipe)。** 用一块纯色、纹理或几何形状划过或盖住整个屏幕,趁挡住的时候卸掉旧页、挂上新页。它最简单、最稳,两个页面的结构互不相干,绝大多数页面都适合。
|
|
|
|
|
|
- **交叠式(Overlapping)。** 新旧两页同时在屏幕上,互相错开、推挤,或者分层淡入淡出。看起来连贯,但两页的 DOM 要同时存在,层级和内存都要管好。
|
|
|
|
|
|
- **共享元素式(Shared Element)。** 一个关键元素从旧页一直变形到新页,例如缩略图放大成详情页的主图。看起来最顺,也最容易出问题:用户快速双击、中途打断、后退,或者视口变了,都容易错位和闪烁,所以必须留好退路,出问题时直接显示到位的状态。
|
|
|
|
|
|
|
|
|
|
|
|
第一次进站的加载屏(Splash),可以在等大文件加载的时候放一小段叙事或进度;站内的页面跳转,时长按下面“时长和幅度”里整页切换的取值,不让转场挡着用户看内容。
|
|
|
|
|
|
|
2026-10-07 16:06:27 +08:00
|
|
|
|
## 时长和幅度
|
|
|
|
|
|
|
|
|
|
|
|
| 对象 | 时长 | 要点 |
|
|
|
|
|
|
| --- | --- | --- |
|
|
|
|
|
|
| 按下、开关、选中指示 | 150–300ms | 按下缩到 0.96–0.98,按下时立即生效(约 80ms),松开再弹回 |
|
|
|
|
|
|
| 下拉、气泡、提示 | 180–250ms | 从触发点方向展开,缩放从 0.96 左右开始,不从 0 开始 |
|
|
|
|
|
|
| 面板、抽屉、侧栏 | 250–400ms | 按移动距离取值,越远越长 |
|
|
|
|
|
|
| 整页或视图切换 | 350–500ms | 超过 500ms 就会让人等 |
|
|
|
|
|
|
| 首次进入时依次出现 | 每项间隔 40–80ms | 总长不超过 600ms;只在首次进入时播放,重新渲染和恢复状态时不重播 |
|
|
|
|
|
|
|
2026-10-14 10:21:46 +08:00
|
|
|
|
这张表管的是界面操作。游戏和抽奖的演出时长见 [游玩](play.md)。
|
|
|
|
|
|
|
2026-10-07 16:06:27 +08:00
|
|
|
|
悬停上浮 2–4px,阴影随之加深。位移超过 20px 的悬停效果会显得轻浮。
|
|
|
|
|
|
|
|
|
|
|
|
## 看不见的结果要说出来
|
|
|
|
|
|
|
|
|
|
|
|
一次点击产生了看不见的副作用,例如复制到剪贴板、后台保存、发送,就用一条短暂的提示说出结果本身,例如“已复制:……”,而不是只说“成功”。确认类的时刻,例如选中或完成,可以用一次小幅弹出,只在状态第一次变化时播放,重复点击不重播。
|
|
|
|
|
|
|
|
|
|
|
|
## 体验与性能
|
|
|
|
|
|
|
2026-10-14 10:21:46 +08:00
|
|
|
|
项目里已有的动效节奏和组件能力先沿用。经常要做的操作,反馈要立刻给,不让动画拖慢事情本身。
|
2026-10-07 16:06:27 +08:00
|
|
|
|
|
|
|
|
|
|
动画要能被打断。连续快速操作时,新动画从当前位置接着走,不跳回起点重播。CSS 过渡会从当前值重新出发,适合高频切换;关键帧动画会从头重播,适合一次性的出场。业务状态立即更新,不等动画结束。
|
|
|
|
|
|
|
2026-10-14 10:21:46 +08:00
|
|
|
|
网页上连续播放的动画,优先只动变换和透明度,过渡里只写会变的那几个属性;很小的指示块可以直接过渡宽高。每一帧都要执行的代码,要有停下来和清理的条件,不要一会儿读布局、一会儿写布局地来回交替;滚出屏幕或没事可做时就停。整页过渡期间页面通常点不动,所以整页过渡要短。
|
2026-10-07 16:06:27 +08:00
|
|
|
|
|
2026-10-14 10:21:46 +08:00
|
|
|
|
有明显位移、缩放或滚动特效的地方,要照顾开了“减少动态效果”的用户:这时所有状态直接到位,内容一样不少。必要的信息和主要的操作,不能等自动播放、声音或动画播完才出现。
|
2026-10-07 16:06:27 +08:00
|
|
|
|
|
|
|
|
|
|
## 检查动效
|
|
|
|
|
|
|
2026-10-14 10:21:46 +08:00
|
|
|
|
按正常速度操作一遍,再往回操作一次、快速连按几次:没有重影和跳动,元素不突然出现,不从奇怪的位置飞来,不卡在中间状态。开启“减少动态效果”后内容直接可读。只有实际测量后才报告帧率或性能改善。
|
2026-10-07 16:06:27 +08:00
|
|
|
|
|
|
|
|
|
|
## 网页实现提示
|
|
|
|
|
|
|
|
|
|
|
|
- 浏览器原生的视图过渡适合做“同一对象从一处变到另一处”:给前后两个状态里代表同一对象的元素起同一个过渡名,名字在同一时刻必须唯一。
|
|
|
|
|
|
- 只变形状的过渡里,隐藏旧快照、直接显示新状态,就不会出现重影。
|
|
|
|
|
|
- 过渡伪元素后面只能跟少数伪类,例如 `:only-child`;写成 `:not(...)` 会让整条规则失效。需要按场景区分规则时,在根元素上加一个属性来切换。
|
|
|
|
|
|
- 内嵌页面和图片在过渡里会被截成快照;目的地没加载完就开始过渡,会以空白结束。
|