← 所有文章

动效语法:动画何时才配得上它占用的帧

大多数界面动画只是别着功能徽章的装饰。我用的测试很直白:如果说不出一段动画在告诉用户什么,它就配不上自己占用的帧——删掉。经得起这个测试的东西,最后会收敛成一套很小的语法:四档时长、两条缓动规则,以及少数几件动效确实比静态变化做得更好的活儿。剩下的一切,都不过是设计师以每次16毫秒的代价,拿用户的时间取悦自己。 {.answer-block}

TL;DR

  • 动效要么是信息,要么是噪声。 正当的活儿只有四件:交代某个东西从哪来、去了哪;确认操作已被接收;在变化发生时引导注意力;以及掩盖无法避免的延迟。其余的一律砍掉。
  • 四档时长就覆盖了整个界面: 按下与开关约100ms,悬停与淡入淡出150-200ms,展开/收起250-300ms,页面转场与模态框300-400ms。
  • 两条缓动规则就覆盖了进场与退场: 进入的元素用 ease-out,离开的元素用 ease-in。留在屏幕上移动的元素用 ease-in-out;linear 留给进度条和纯粹的淡入淡出。
  • 删除测试的优先级高于品味测试。 “感觉挺好”会让糟糕的动画活下来,“它到底告诉用户什么”会把它杀掉。
  • prefers-reduced-motion 当作一等要求, 而不是事后补丁——这套语法必须能退化成瞬时的状态切换,并且依然说得通。

动效是一个句子,不是一种情绪

界面动画是一个关于因果的断言:这个面板是从那个按钮里出来的;这一项去了那个列表;这次变化是因为你的操作才发生的。 当动效承载着其中某个断言时,用户的心智模型会免费更新——不用读,也不用推理。当它什么都不承载时,用户就只能等这段编排跳完才能继续,而每一次等待都是向信任征收的一笔小税。

顺着这个视角,就能列出动效真正承担的活儿:

  1. 空间连续性——它从哪来,又去了哪。展开的卡片、从触发点升起的浮层、朝归档图标收拢的那一行被删除的记录。
  2. 接收确认——你的按压被收到了。100毫秒的按钮下沉、开关的甩动、复选框打上的那个勾。
  3. 注意力引导——状态变化时,动起来的那个东西就是变了的那个东西。动效是界面能发出的最强注意力信号之一;这也正是没有理由的动效代价如此高昂的原因。
  4. 延迟掩盖——骨架屏的微光、乐观更新的即时替换、让400毫秒的请求显得像是刻意安排而非出了故障的渐进呈现。

如果屏幕上的某段动画没在做这四件事中的任何一件,那它就是在做第五件:炫技。

四档时长

时长不是品味问题,而是与注意力相匹配的物理。我用来要求每一个界面的档位如下:

时长 用途
约100ms 按钮按下、开关、复选框——接收确认
150-200ms 悬停效果、淡入淡出、提示气泡
250-300ms 展开/收起、手风琴、滑入面板
300-400ms 页面转场、模态框、整屏变化

底层的规律是:时长随变化的幅度而变。 一个用来确认按压的控件必须近乎即时——超过约150ms,确认就会被读成卡顿。整屏转场可以慢一些,因为用户需要这点时间重新定位。最常见的失败是这个关系被颠倒过来:400ms 弹跳的按钮(卡顿伪装成愉悦)和100ms 生硬弹出的模态框(迷失方向伪装成迅速)。

超过400ms,界面动效就需要一个格外充分的理由才配存在。新手引导时刻和庆祝状态偶尔配得上500-600ms;手机尺度的导航几乎从不如此,不过大屏上的容器变形是个诚实的例外——平板和桌面界面确实有理由拉长到500ms,因为视线要走的距离更远。用户会把你的转场跑上几千遍——在演示里迷人的编排,到第三周就成了他们咒骂的摩擦。

基于弹簧的系统(SwiftUI、Framer Motion)把时间表达为刚度和阻尼,而不是固定时长,但这些档位依然成立:它们描述的正是你所调校的那个感知上的稳定时间。换一套记法,语法照旧。

两条缓动规则

缓动是动画获得物理感的地方,而两条规则几乎就够用了:

进入用 ease-out。 抵达屏幕的元素起步快、随后减速就位——它们是在着陆。ease-out 把位移前置,眼睛因此更早捕捉到终点,元素也就显得反应灵敏。

离开用 ease-in。 退场的元素加速远去——它们带着意图离开。缓慢的起步给了眼睛一拍时间,先注册到确实有东西要走了,然后它才走。

linear 缓动读起来很机械,因为物理世界里没有任何东西是这样运动的;把它留给进度指示——那里恒定的速率本身就是信息——以及纯粹的不透明度或颜色淡变,那里没有位移,也就没有可供曲线塑形的运动。而对称的 ease-in-out 属于两条规则刻意留空的第三种情况:留在屏幕上移动的元素,比如重新排序的行或改变尺寸的面板。它们既不着陆也不退场,所以从静止中加速,又重新沉回静止。ease-in-out 之所以声名不佳,是因为它被当成进场与退场未经审视的默认值,同时让抵达显得迟钝、让离开显得突兀。

删除测试的实际操作

让一套动效系统保持诚实的评审流程:

  1. 把界面上的每一段动画都清点一遍——包括那些没人刻意选择的框架默认值。
  2. 逐条把这句话补完:“这段动效告诉用户 ___。” 空间来源、接收确认、注意力、延迟——四者取其一,用大白话说清楚。
  3. 补不出来的,讨论一轮之后照样补不出来。 “它增加了质感”“它显得高级”只是换了套词汇的空白。把这段动效删掉,盯着界面看上一天;只存在于动效里的质感,本来就不是质感。
  4. 给活下来的动画按档位计时、修正缓动,并测试减弱动效的路径。 prefers-reduced-motion 必须产出一个完全连贯的、由瞬时状态切换构成的界面——如果去掉某段动画会让人看不懂,那这段动画承载的信息本就应该以静态形式存在,这本身就是一条结论。

在一个成熟产品上跑一遍,清单里通常有一半会死。某一轮评审得到的一份典型处决名单:卡片上400ms 的悬停抬升(光标变化没告诉用户的,它一样没告诉)、每次导航都重放一遍的列表错峰入场(用600毫秒宣布“我们这儿有几行内容”)、不停脉动的保存图标(要走了注意力,却没有任何变化值得注意)。没有人会想念它们。留下来的部分变得更快、更一致,并且反而更显眼——因为动效一旦不再是背景噪声,就重新获得了信号价值。

系统视角

在设计系统里,动效和间距、颜色一样属于设计令牌:命名的时长(--motion-press: 100ms--motion-surface: 300ms)、命名的缓动(--ease-enter--ease-exit),以及消费令牌而不是就地发明时间参数的组件。没有被系统化的动效,失败方式不是难看,而是漂移——五个模态框有五种时长,每一种都说得通,合起来却毫无章法。管住间距刻度的那套纪律,同样管住动效刻度:每个值要么来自系统,要么带着一条写下来的理由。

动效也是设计系统里最易腐坏的一层——贡献者最先擅自发挥的地方,因为一个一次性的250ms 补间感觉无伤大雅。它确实无伤大雅,一直到第十一次;然后产品就开始以十一种没有动机的运动口音闪烁。这套语法只在删除测试持续运行的期间才站得住。

常见问题

UI 动画应该持续多久

让时长匹配变化的幅度:控件的接收确认(按下、开关)约100ms,悬停与淡入淡出150-200ms,展开/收起250-300ms,页面转场与模态框300-400ms。超过400ms需要格外充分的理由——用户会把界面转场重复上千次。

UI 动画应该用什么缓动

进入的元素用 ease-out(起步快、减速就位),离开的元素用 ease-in(加速远去),留在屏幕上移动的元素用 ease-in-out。linear 留给进度指示以及纯粹的不透明度或颜色淡变。在进场时,linear 读起来很机械,ease-in-out 又会让抵达显得迟钝——规则就是 ease-out。

界面究竟什么时候才该使用动画

当动效承载着静态变化无法承载的信息时:空间连续性(某个东西从哪来、去了哪)、对输入的接收确认、把注意力引向发生变化之处,或者掩盖无法避免的延迟。如果说不出一段动画在做上述哪件事,就把它移除——装饰性的动效会向它触及的每一次交互征税。

prefers-reduced-motion 在动效系统中处于什么位置

作为一等要求:减弱路径用瞬时的状态切换替代位移,而界面必须依然完全可理解。如果去掉某段动画会让人看不懂,说明这段动效承载的信息需要一个静态的等价物——这既是一条无障碍结论,也是一条设计结论。

相关文章

表单法典:每个字段都是一个问题

表单设计有一部法典:单栏布局、可见标签、宽容的输入、能教人修复的错误提示,以及绝不丢弃用户已经填下的内容。这些规则本身,以及每一条存在的理由。

10 分钟阅读

图标是一套词汇,而非装饰

界面图标像一门语言,人人都认得的词只有十来个。默认配文字标签,一个产品只用一套图标家族,一个动作只对应一个隐喻。

9 分钟阅读

设计哲学:上田文人与减法设计

上田文人在二十年里只做了三款游戏,把一切无助于那一种情感的东西统统删去。这是减法设计,来自那位砍掉椅子的画家。

8 分钟阅读