给下拉菜单加一个轻轻放大的出场,是很常见的做法。但我用过的不少菜单,放大起来像是“出现在按钮旁边”,而不是“从按钮里打开”。问题出在放大的中心点:默认情况下,菜单从自己的正中间放大,跟打开它的那个按钮没有任何关系。
✕ 从自己的中心放大
打开慢放,盯住菜单贴着按钮的那条边:它先出现在离按钮有一段距离的地方,再往按钮那边“够”过去。三个菜单的动作一模一样,看不出谁是谁打开的。
✓ 从触发按钮那一侧长出来
贴着按钮的那个角从头到尾都不动,菜单从那里铺开。左上的按钮从左上角长,右上的从右上角长,右下的帮助按钮从右下角往上长。
01放大总要有一个中心点,默认是元素自己的正中间。对挂在按钮上的菜单来说,这个默认值几乎总是错的。
02中心点放在按钮那一侧:按钮在左上,就从左上角长;菜单在按钮上方弹出,就从下沿往上长。弹出方向变了,中心点也跟着变。
03正常速度下,很少有人说得出它是从哪个角长出来的,但会觉得这个菜单是从按钮里出来的,而不是凭空出现在旁边。
为什么这样更好#
- 动作交代了来处。菜单从按钮那一侧铺开,眼睛会顺着动作把它和按钮连起来,不用再去确认“这是刚才那个按钮打开的吗”。
- 贴着按钮的那条边不会乱动。从中心放大时,菜单的每一条边都在移动,包括紧贴按钮的那一条,看起来就像菜单先离开了按钮,再被拉回来。从按钮那一侧长出来,那条边从头到尾都待在原地。
- 不同的按钮有不同的动作。左上、右上、右下三个按钮,菜单分别往右下、左下、左上铺开。弹出方向本身就成了位置信息,而不是三个一模一样的动画。
- 跟着弹出方向走。菜单在按钮下方,就从上沿长;空间不够、翻到按钮上方弹出时,就该从下沿往上长。中心点要跟着实际位置变,而不是写死一个方向。
- 细节会累积。正常速度下没人会注意到这个差别,但一个产品里这类细节都做对了,它们会叠加起来,整体就会显得更顺。
现在常用的组件库,比如 Radix UI 和 Base UI,都会根据菜单实际弹出的位置,自动算好这个中心点交给你用。用这些组件的时候,记得把它接上,不要让它停在默认的正中间。
什么时候不该用#
- 对话框这类不挂在某个按钮上的弹层,本来就没有“来处”,从屏幕中央出现更合理。
- 用户在系统里开了“减少动态效果”,就直接出现,不播过程。
- 一天要打开几百次、主要靠键盘触发的面板,比如命令面板,最好连动画都不要,也就谈不上从哪里长出来。
出处#
来自 Emil Kowalski 的 7 Practical Animation Tips ↗ 第 5 条 “Make your animations origin-aware”。他指出放大的中心点默认在元素正中间,对弹出层来说多半不对,并顺带提到 Radix UI 和 Base UI 都提供了现成的原点变量。