能随时打断、不回弹的动画
连点两下一个控件,动画不该从头再来。这篇讲这个网站上的动效怎样接着原来的位置继续走,以及为什么控件上的弹簧都不回弹。
拨一下开关,圆钮滑过去。滑到一半再拨一下。如果圆钮跳回起点、重新从那里出发,就会觉得哪里坏了,哪怕整段动画单独看很漂亮。
原因在于,这种动画是一条定时长的曲线:300 毫秒,从这里到那里。你中途改主意,曲线并不知道圆钮刚才在哪儿、速度多快,只会从头再来。
从原来的地方接着走
弹簧不按时间想事情,它只认目的地。圆钮想去某个位置,每一刻它都知道两件事:自己在哪儿,跑得多快。中途换了目的地,这两样都原样保留,变的只是弹簧往哪边拉。圆钮会像一个有分量的东西那样减速、掉头,没有跳变,也没有重启。
我的测试办法不太雅观:每 100 毫秒反向一次,持续一整秒,看位置有没有哪一刻突然跳变。有个常见的坑是带弹性曲线的 CSS transition。它摸起来像弹簧,本质上仍是一条定时长的曲线。只要用户能在半路把它反向,就该用真正的弹簧。
为什么都不回弹
弹簧会不会回弹,取决于阻尼有多大。有一个确切的临界点,叫临界阻尼,在这个点上它以最快的速度到达,而且一点也不会冲过头。这个网站上控件用的弹簧(按压、圆钮、标签页、面板)都落在这个点上或者更高,所以到了就停住。
控件上的回弹,看起来像玩具。第一次看觉得可爱,天天都要碰就嫌碍事。所以动效文件里只有一条会冲过头的弹簧,还专门给它起了名字,免得有人不小心用上。它只用于一次性的庆祝,冲过头大约 1.5%,绝不用在控件上。
所有弹簧都放在这一个文件里。控件上的那些来自 Material 3 的动效方案:一条管位置移动,另一条更硬的管透明度,这样淡入淡出不会落在它所配合的移动后面。跟随指针或滚动的效果,比如首页那张人像的视差,用的是手工调过的弹簧,同样不回弹。
屏幕上的东西动起来,我希望它听手的。手改了主意,动画就跟着改。