在 2025 年 1 月,我与设计师完成了两个项目,它们分别是 视频号互选创作者榜 和 朋友圈广告年度评选。我们共同完成了一些有趣的交互动画,其中包含了我对这个领域的理解与追求。
这篇文章的标题是《制作流畅界面》,来自于 WWDC18《设计流畅界面 Designing Fluid Interfaces》。这个 7 年前的视频对我影响极大,我看过它许多遍、将它视为指引的灯塔。接下来,我将通过几个具体案例,分享自己是如何学习与制作流畅界面的。希望这个对我职业发展有重要意义的视频,也能让你觉得有所收获。
我们从最基本的开始。
流畅界面的基础,是保证实时的反馈。
人们对延迟非常敏感。当发生任何时延迟时,就会感到脱节,交互不再像是自己手指的延伸。
—— 设计流畅界面 05:47
在上面的案例中,随着手指的向下滑动,首张卡片会向下移动,整叠卡片也会实时响应。一般来说,完全的实时是没有问题的,不过在这个案例中还可以优化。
正是因为我们需要首张卡片尽快地向下移动,它的每次 Y 轴位移距离就可能比较大,可能接近 10px
。在上面 60 帧的视频中你可以看到这种跳跃的变化 —— 实时的变化不一定让人感到连续。
// 实时变化的值
const rotate = useMotionValue(0)
// 连续变化的值
const rotate = useSpring(0, {
visualDuration: 0.1,
bounce: 0,
})
// 实时变化的值
const rotate = useMotionValue(0)
// 连续变化的值
const rotate = useSpring(0, {
visualDuration: 0.1,
bounce: 0,
})
我们可以将实时变化的值,变成一个硬度(stiffness)非常强的弹簧动画,你可以理解为现在这根弹簧“冲击力”极强,曲线会是这样:
这会让变化更加连续,使每一次的变化在 5px
左右。这样当然会同时引入一点延迟,但只是不会感知到的一点点:
现在,我们就实现了一个实时且连续的反馈。
上面所说的实时的反馈看起来理所当然,但如果结合 UI 的各种状态仍要做到实时的话,事情就会开始变得复杂。
我们发现,让界面始终具有响应性、始终理解用户是非常重要的。这对用户的预期和对界面的理解来说非常关键。这样用户才能感到舒适,并意识到每当需要时,界面都会及时响应。
—— 设计流畅界面 09:44
在 Apple iOS 的例子中,当用户打开一个 app 时,他可以在过渡过程中就选择关闭它。用户不需要等待任何过渡的完成和停止。这也是交互动画与视觉(非交互)动画的一大区别 —— 过渡不只是一种形式。
这意味着,所有的动画都要关注:播放到一半,滑走会发生什么;以及滑走后,马上又回来,怎么办?繁琐的工作就在这里,因为我们的转盘涉及到元素和背景的变化。
比如,在去年的转盘入场过程中,用户不能打断它,它只是一种形式。而今年,用户可以在任何时候决定如何开始:
根据统计结果,接近一半(45.71%)的用户不会等到入场结束再操作。
转盘还在转动就能投票;不需要等待投票动画结束,不想看就滑走:
根据统计结果,有 36.77% 的用户在转盘还在转动时进行投票。
在 视频号互选创作者榜 中也一样,你随时可以点开卡片查看更多信息,也可以在卡片翻转的过程中选择关闭它:
流畅的界面要始终具有响应性,可打断、可反悔。允许用户在每一个状态变化的过程中,都可以将他的手指按下,界面随他调度。
当用户松手时,流畅的界面应该响应速度,保持惯性。有的时候还需要奖励动量(momentum),最常见的就是橡皮筋效果(rubberband)的例子。
从一个短暂、轻量的交互开始,通过位置、速度、加速、力量,放大你移动的结果,让你仍觉得是自己的延伸。通过轻量的交互,就能得到愉悦的感受。
—— 设计流畅界面 15:06
以上的两种交互的表现是类似的,都围绕着 “松开手之后,应该停在哪?” 和 “停到那个地方,要花多久?” 这两个关键问题展开。过去已经讨论过,在这篇文章中不再展开。
奖励动量发生在下面的场景:当用户点击左右两侧卡片时,转盘也会转动,但是这个过程不会有回弹效果;而当用户滑动后,转盘就会带有一个回弹,这就是一种对动量的奖励,也更用户明确:已经到达最终位置了,你可以继续交互了。
这样的细节我觉得是合理的,是有趣的。
流畅的界面还可以通过让操作与想法并行,让用户不需要在决策前花费额外的时间。
线性的界面迫使用户先思考、再做决定、然后交互。而流畅的界面思考和手势是同时发生的,这比先思考再交互要快得多。
—— 设计流畅界面 08:24
我们对此也做了一些有意思的尝试,虽然我觉得确实有一些“牵强附会”。
在用户点击右上角 Tab 进行切换时,这叠卡片会做一个单方向的 Shuffle 动画。而如果用户不抬起手指,它则会一直保持这个状态。你不需要着急,也可以上下拖动,最后决定好了再松手:
从统计结果上来看也很少有用户这样使用,有 2% 的用户会交互 2 秒及以上。但是这种尝试是有意义的,因为它赋予了交互以可探索性。当某个用户发现了这个功能,他或许会觉得有趣。而当我们在实现了上面的实时、连续、可打断、响应速度、惯性...这些所有特性之后,最后加上这个功能,这一叠卡就突然变得更完整。不,不应该说是完整,而是就 更像一叠卡 了。
好,我们可以接着往下问,为什么就要真的像一叠卡呢?
在《设计流畅界面》的最后一部分,Apple 的设计师要将流畅性作为一种媒介(Fluidity as a Medium)。“媒介”这个词虽然不太日常,但我们又不能简单地说:把流畅性作为设计目标。因为这体现不出“媒介”这个词的妙。媒介:能使人与人(人与事物或事物与事物)之间产生联系的物质。
第一次看到上面这一页的内容时,我佩服 Apple 的设计师。我看过蛮多 Interface Guidelines 或者组件库设计原则,它们通常会告诉你多少秒算快、多少秒算慢,它们列举 ease-in、ease-out,它们说动效要明确、清晰、流畅、自然、理解、聚焦、共情... 不知从哪天开始,我觉得我懂了,我不需要再听这些原则了,我学够了,我已经有感受了,我知道如何分辨了。
—— 只是,当我想要实现这些我都懂了的体验时,我好像没有设立一个实际的目标。
Apple 的设计师说,流畅本身就是传达信息的媒介,要把流畅与否作为设计目标。除了文本、图片、视频这些媒介,除开这些“看得见”的,还要有“摸得着”的目标。这是我没有听到过的。
视觉与交互不可分割,当一叠卡摆在面前时,它最好就是一叠卡;当一个转盘摆在面前时,它最好就是一个转盘。如果用户觉得你的设计看起来可以这样交互,那么你最好满足他,否则你就不要长那样 —— 说起来又像是理所当然的废话了。
当你真正地完成了一个流畅的界面,你就会发现它很难被直接复制,因为它体现了对所有细节的理解。甚至,能赋予产品独特的“性格”。
在评选选择标准的列表上,我加入了类似 Apple Message app 的列表滚动效果。每个元素不再是以一个整体的形式滚动,而是各自有一些细微的错落:
我曾在《交互动画的层级设计》中探讨过这种形式。错落的形式并不妨碍我们很自然地将它们视为一个整体。可是,为什么要这样做呢?
这里的具体做法是将每一个元素的位移都分开计算。
// 这几个数字的调整花了我不少时间
{
tension: 1200 - deltaIndex * 15,
friction: 26 + deltaIndex * 5,
clamp: true,
}
// 这几个数字的调整花了我不少时间
{
tension: 1200 - deltaIndex * 15,
friction: 26 + deltaIndex * 5,
clamp: true,
}
把具体的数字打出来看看:
比如当用户向上滑动时,页面顶部的元素就会连续地变换到 tension: 1200, friction: 26
,而页面底部的元素则会连续地变换到 tension: 1035, friction: 81
。就是因为整个过程都在 连续不停地变换,整个滚动过程才顺畅。它们两个(即头尾元素)的差异换算成时间大概是 0.15s
和 0.2s
:
但时间和参数的数字并没有用(时间只是物体运动的结果,而非原因),还是需要拿在手上不断调整。比如在惯性滚动时,我将 timeConstant
调整为 150
,这会导致衰减得更快,列表停下来就更快,细看就会发现这点 —— 因为这里的需求并不是浏览长列表的效率。不展开了。
也可以在下面的 Demo 中粗略体验,调节一下参数试试:
如果我们再把话题往上拔,当你掌握了制作流畅界面的所有技巧,当你赋予了产品品质。流畅界面的最后是什么?这场分享还有一句令我佩服的话:
好玩,是流畅界面的自然结果。
也许交互动画的最终目标,就是好玩。好玩因为界面永远响应你,好玩因为你有兴趣探索可能的交互。好玩是流畅界面的自然结果。
而我还在不断精进、不断更深入地理解这些话。
Apple 的设计师能说出这样“独特”的话,让我感叹他们果然是优秀的实践者。我也同样在实践与尝试中试图理解这些话。只有动手做了,才知道实现一个看起来简单的动画有多少容易忽略的细节。
作为实践者,我还需要关注性能。比如,今年对整个转盘做了 React 的 render 优化,实际在转动时只有 5 张卡片:
这一叠卡就是 6 张更换位置,这样实现也最方便:
以及渲染 40 个标准列表也只会让屏幕内的元素显示,成为了那个页面中最流畅的交互动画。当然这些都不困难,是应该做到的。
还有在合适的地方加入 will-change: transform
,它对安卓还真的有用;还有不要以为 svg 方便就是万能的就乱切,svg 里面的 filter
会造成卡顿;linear-gradient
在低版本 Safari 也会有问题...
这两个项目中的大小问题,我不会在这篇文章中再展开。还有数字动画、投票动画也令我挺满意,但都不是这篇文章的主题。因此我将我遇到的问题和经验另外集合写了一篇《Web 流畅界面建议》。
交互动画这个领域,属于我们做 UI 的工程师。
想对各位设计师朋友说:
不知道大家有没有过这种时候:当你用几句话也很难描述自己理想的体验,或者在 Figma 里通过标注还是觉得很难形容,然后发现自己从前读过的动效规范帮不了你更多。那么恭喜你,你可能正站在一扇门面前。这扇门的背后非常有趣。
接下来你需要拿起你的手机坐到你的工程师面前,你要把这个视频发给他,你要跟他说我们要做的事比拉一条贝塞尔曲线有趣得多。要花更多的时间去做快速验证。最重要地,要把你的想法转换为开发者自己的想法。你们要做好玩的事。对,只是做流畅的界面而已。