Files
workbuddy_skills/oil-ui-pro/references/motion.md
T

12 KiB
Raw Blame History

动效

每个界面先做三处动效

完全不动的界面像一张截图:按下没有回应,切换没有来路,用户只能猜刚才发生了什么。新界面和改动了操作流程的界面,先把这三处做出来,手感写进方向卡的“动效”一栏:

  1. 主操作的反馈。 按下立刻有回应,完成时交出一个结果:按钮陷下去再弹回,勾号画出来,数字滚到新值。
  2. 一处状态切换的来路。 选中、展开、换视图、增删列表项时,让人看见东西从哪里来、到哪里去,见下文“界面过渡”。
  3. 第一次进入时的一次出场。 主角先到,其余按阅读顺序跟上,只在首次进入时播放。

这三处之外再加动效,先问:如果要手写一周才能做出来,还值得做吗?模型让动效变得免费,但滚动淡入、视差、跟随鼠标和装饰性循环最容易变成干扰。每个动效都要承担反馈、引导、连续或品牌表达中的一项。

目的 适合考虑的方式
按下、聚焦、展开或普通状态变化 原生能力或已有组件的小范围过渡
视图之间的切换、元素换位置 共享元素过渡,见下文“界面过渡”
拖拽、手势、空间变化与复杂编排 项目已有成熟动效能力
特殊品牌画面、材质、复杂物理效果 图片、3D、着色器或预渲染视频,按需求取舍;着色器能做的效果见 点缀与特效
鼠标、触控或滚动控制叙事进度 将输入映射到明确的动画进度,处理反向和快速操作;思路见下文“滚动叙事”

代码动画适合需要精确状态控制的界面,生成视频适合预先确定的视觉变化;不能用视频替代需要动态数据与真实操作的控件。

手感

动效的手感从方向的材质和调性推出,用“动作 + 实物”来命名和选参数(弹簧刚度 / 阻尼):

动作 实物参照 刚度 / 阻尼 适合
咔嗒 磁铁吸合、卡扣、拨动开关 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。

呼应:让动作彼此接上

生硬的动效各动各的:按钮自己闪一下,面板自己滑出来,数字直接换掉。好的动效像一句话:一个动作引起的变化沿同一条路传下去,前一段的终点是下一段的起点。

  • 从被操作的地方出发。 点“加入购物袋”,商品缩成一个点飞进袋子,袋子上的数字跟着跳一下;删掉一行,它朝删除按钮的方向收走,下面的行补上来。
  • 一次切换朝一个方向。 卡片往左滑,标题、序号和底色也往左换;数字往上滚,进度也往上涨。方向一乱,就成了几段互不相干的动画。
  • 主角先动,其余被带动。 被影响的东西晚 40–80ms 跟上,幅度更小,像被主角拉过去的。全部同时起跑、同样幅度,看起来只是一起闪了一下。
  • 形状接力。 上一个状态里的元素变成下一个状态里的元素:按钮展开成面板,搜索图标拉长成输入框,播放键变成暂停键。用户一眼看出它们是同一个东西。
  • 动法和画面是同一种材质。 纸面的方向,切换轻、有一点停顿;硬件的方向,开关有咔嗒到位的感觉;液体和玻璃的方向,用流淌和折射。

巧思从产品里找

巧思是让一处动效讲出这个产品自己的事,不是加更多花样。从内容里找一个只有它才有的动作:

  • 天气应用切到雨天,雨点落在卡片上;雨停以后,卡片上的水痕慢慢干掉。
  • 记账应用记下一笔支出,预算条少掉的那一截落进这笔账里。
  • 音乐播放器换歌,新封面的颜色从唱片中心漫到整个背景。
  • 完成待办时,勾号用和品牌标志相同的笔画画出来。

找不到这样的动作,就把三处基本动效做准,不硬造。一页最多一两处巧思,其余动效安静、短促。

界面过渡

连续。 用户点的东西就是下一屏的主角。从列表进入详情,被点的那一项放大成详情,其他项淡出;返回时它缩回原位,页面回到原来的滚动位置。原位已经不在视口里,就先把它滚到可见,再缩回去。

方向一致。 下一项从右边进,上一项从左边进;打开和关闭互为逆过程;侧面板从它所在的那一侧滑入滑出。方向随意的动画比没有动画更让人迷惑。

只变形状时不做交叉淡化。 切换视口、筛选、展开说明、缩放,这类变化里内容还是同一个东西,只是尺寸和位置变了。让外框直接变形,内容立即显示新状态。交叉淡化会让新旧两张缩放不同的画面叠在一起,出现重影。只有内容本身换了,才淡入淡出。

离开、加入、留下分开处理。 被移除的淡出,新加入的淡入,留下的滑到新位置。三者用同一种淡化,列表就会整片闪烁。

选中指示用一块会移动的滑块。 分段控件、标签页、列表当前项,都用同一块底板滑到新位置,而不是旧的熄灭、新的点亮。选项宽度不同时,宽度一起过渡。首次显示、窗口缩放和字体加载完成后直接放到位,不要从 0 宽度长出来。

先准备好目的地。 目的地要加载的内容,例如图片或内嵌页面,先加载或预先渲染好,否则动画会停在一块白屏上。需要来回切换的视图预先渲染并留在页面里,切换时只移动,不重新加载。内容加载完成后再淡入,不先闪一下白底。

离开比进入快。 退出时长约为进入的 60–70%,用加速曲线;进入用减速曲线或弹簧。

到头要有反馈。 已经是第一项或最后一项时,轻轻顶一下(往返 10–15px),而不是毫无反应。

时长和幅度

对象 时长 要点
按下、开关、选中指示 150–300ms 按下缩到 0.96–0.98,按下时立即生效(约 80ms),松开再弹回
下拉、气泡、提示 180–250ms 从触发点方向展开,缩放从 0.96 左右开始,不从 0 开始
面板、抽屉、侧栏 250–400ms 按移动距离取值,越远越长
整页或视图切换 350–500ms 超过 500ms 就会让人等
首次进入时依次出现 每项间隔 40–80ms 总长不超过 600ms;只在首次进入时播放,重新渲染和恢复状态时不重播

悬停上浮 2–4px,阴影随之加深。位移超过 20px 的悬停效果会显得轻浮。

看不见的结果要说出来

一次点击产生了看不见的副作用,例如复制到剪贴板、后台保存、发送,就用一条短暂的提示说出结果本身,例如“已复制:……”,而不是只说“成功”。确认类的时刻,例如选中或完成,可以用一次小幅弹出,只在状态第一次变化时播放,重复点击不重播。

滚动叙事:视差与一镜到底

滚动当作翻页,它只是翻页;当作摄影机的推拉,页面就能讲故事。品牌、发布和叙事页可以这样做,文档、文章、工具和后台不做;一页最多一段。记忆点先放在用户会做的动作上(点按、拖动、悬停),再考虑滚动;不要把整页做成视差秀。

  • 一镜到底。 整段是一次不切换的镜头。一个主角从头走到尾,可以是产品、一根线、一个形状或一个字,每一步长成、变成或让出下一个画面:推近看到细节,拉远看到全貌,转过去看到背面,穿过去进入下一个场景。动手前先画分镜:每个镜头占多少滚动距离、画面里有什么、什么在动、文字什么时候出现。
  • 停下来再说话。 每个镜头留一段静止,文字在静止时出现;边动边读很累。
  • 视差要有真实的前后。 只在画面本来就有远近层次时用:前景的物体、中景、远处的背景,越近动得越多,差别要小。文字不做视差。
  • 转场也是镜头。 一个圆从某一点扩开,带出下一节;推进一张图,穿过它到达下一节;背景色在章节之间随阅读慢慢变;一句宣言随滚动逐字亮起。每种手法一页只用一次。
  • 倒着滚也成立。 每一帧只由滚动位置决定,往回滚自然倒放,刷新或跳到中间也立刻是对的画面。不接管用户的滚动。
  • 留出口。 长段落前给一个跳过入口;减少动态效果时,把每个静止画面按顺序排成普通区块。
  • 代码做不出来的,交给视频。 用户想要很强的首屏动画,而效果要靠生成视频或序列帧才做得出来,例如角色转身、产品拆解、镜头穿越场景,可以告诉用户用 oil-motion 来做。CSS、SVG、着色器能完成的仍自己做;同一次对话只提一次。

体验与性能

沿用项目的运动节奏和组件能力。高频操作反馈直接,不让动画延迟业务完成。

动画要能被打断。连续快速操作时,新动画从当前位置接着走,不跳回起点重播。CSS 过渡会从当前值重新出发,适合高频切换;关键帧动画会从头重播,适合一次性的出场。业务状态立即更新,不等动画结束。

网页连续动画优先用变换与透明度,只声明需要变化的属性;小尺寸的指示块可以直接过渡宽高。逐帧工作要有停止和清理条件,避免频繁交错读写布局,离屏或无任务时停止播放。整页过渡期间页面通常不响应点击,所以整页过渡要短。

明显位移、缩放和滚动特效,要为“减少动态效果”提供等价呈现,此时所有状态直接到位。必要信息和主要操作不能依赖自动播放、声音或动画完整结束。

检查动效

静态截图证明不了动效。三处基本动效和动效记忆点都要留证据:一段 3–5 秒录屏,或开始、中间、结束三帧,并写明触发它的动作。把播放速度调到 10%,可以用浏览器开发者工具的动画面板,或自动化工具里的动画倍速,在过渡进行到一半时截图。看有没有重影、跳动、元素突然出现,或者从奇怪的位置飞来。逐个检查开始、中间、结束和反向;再快速连按几次,确认不会卡在中间状态。最后开启“减少动态效果”再走一遍。只有实际测量后才报告帧率或性能改善。

网页实现提示

  • 浏览器原生的视图过渡适合做“同一对象从一处变到另一处”:给前后两个状态里代表同一对象的元素起同一个过渡名,名字在同一时刻必须唯一。
  • 只变形状的过渡里,隐藏旧快照、直接显示新状态,就不会出现重影。
  • 过渡伪元素后面只能跟少数伪类,例如 :only-child;写成 :not(...) 会让整条规则失效。需要按场景区分规则时,在根元素上加一个属性来切换。
  • 内嵌页面和图片在过渡里会被截成快照;目的地没加载完就开始过渡,会以空白结束。