James Coombs是一位设计工程师,负责维护产品设计系统中的图标和插画体系。他花了一周时间,才让一个插画按照设计师Figma原型的方式在两个状态之间完成动画过渡——而这一周的大部分时间,都用来弄明白那个显而易见的方案究竟为何失败。

显而易见的方案是这样的:你有两个SVG,同一个插画的两种姿态,你想让它在两者之间动起来。SVG本质上是路径的列表,每条路径又是一串字母命令(移动、画线、曲线)加上定位用的数字。所以要做动画,就对数字做插值:在中间帧,每个坐标都恰好落在起点值和终点值的正中间。90%的插画这样处理都能完美动画。剩下10%在空中散架。

散架的部分是一个边移动边旋转的圆形。逐帧回放时,你会看到路径碎片从自身形状上脱落、飞散开来,像一张爆炸示意图。

在讲机制之前先说明一点:已经有很多库在做SVG形变(MorphSVG、Flubber、KUTE都在其中)。我不是要重新实现它们。我关心的是它们隐藏的机制,外加两件现成库不会直接给你的东西:如何从设计师的两个姿态中还原刚体运动,以及一个会在任何库看到形状之前就把它们腐蚀掉的构建管线陷阱。

为什么对点插值转不起来

旋转不是对坐标的线性操作。当一个形状旋转时,每个点都沿弧线运动,落在哪里取决于正弦和余弦。单独对每个x和y做插值,等于画了一条直线捷径,径直穿过弧线而过。对一个只做平移的形状来说,这条捷径和弧线本来就是同一条线,所以不会出问题。但旋转时两者分道扬镳:混合出来的形状会朝动画中间向内收缩,转动也不均匀,一边缩小一边……