如何用AE表达式制作摇摆的铃铛

在一个阳光明媚的下午,我在生产力工具iPad上看剧,频繁的消息提醒让我不得不注意到了这个按钮:

工具/原料

电脑

AE软件

方法/步骤

精巧的物理动效让我瞬间流下了没有技术的泪水。痛定思痛,我开始琢磨如何来实现这个动效,当然第一时间我肯定想到了万能的K帧,然后付诸了行动,步骤和最终效果如下:

1、绘制铃铛

整理图层关系。使用AEUX插件将在Sketch中绘制的铃铛图标同步到AE中,用AI绘制的铃铛也可以导入到AE中(具体操作请咨询搜索引擎),设置合成帧率为60帧/秒(为体现动画细节和便于计算,本文全部案例的合成均为60帧/s),并将图层关系组织成下图的样子,组织完毕将在合成窗口中得到右侧的图形。

打关键帧。设置铃铛罩的旋转中心点并在旋转属性上打下关键帧,由于铃铛芯是被罩子带动而进行摆动的,所以复制罩子的旋转关键帧粘贴到铃铛芯并往后一点错位放置,利用两个部件运动的时间差就能做出铃铛罩子先动带动铃铛芯后动的效果。如下图所示:

播放。动画效果如下:

显然这样的效果没脸说精巧,铃铛晃动几下就停了,如果想持久一点就需要打上更多的关键帧,还要保证从动画曲线上看这个衰减过程是平滑有规律的,可是我拿什么保证呢?我怎么可能给你手动那么多帧。

后来我就想到了表达式——在AE大神之间流传的一种独门秘法,传说只要写几行代码,就能自动生成行云流水的动画。

于是,我开始为此求索。

在AE中图层或图形的属性都会对应一个或者一组参数,动画的本质就是特定属性参数的持续变化。比如,一个图形在1秒内顺时针旋转了90度,即该图形的旋转属性(Rotation)参数在1秒内在初始值的基础上累加了90,当我们按住Alt键并点击旋转属性左端的小秒表时就会在右边原来打关键帧的区域出现表达式的输入框,在这个框中输入数值,就相当于把这个值赋给所对应的属性,在旋转属性下的表达式输入框中输入90就表示该图层/图形的旋转角度为90度,即便时间指针走动,它依然保持90度,这种情形下这个图层/图形是静态的。

但如果我们输入的是一个公式,这个公式能根据某个参数变化产生不一样的值,比如能根据时间的变化(时间指针的走动)持续计算出新的结果,那动画就产生了,这个公式就是表达式了。举例,我们在旋转属性下填入以下公式:

time*90;

time是AE系统时间变量(即那根走动的指针),从0开始累加,当累加到1的时候表示时间从0秒走到1秒,time*90则意味着在1秒时间内,该图层/图形旋转角度从0度逐渐变成90度,再走0.5秒,就再旋转45度。

路漫漫其修远兮,我了解了表达式的基本用法,但是想更进一步却毫无头绪。我要通过一个怎样的表达式产生出一组连续的运算结果使得铃铛来回摆动呢?

正弦函数!

很快的,我实现了一个永不停摆的铃铛罩子,用到的表达式只有一句:

r=Math.sin(time*10)*100;

Math.sin是AE中正弦函数,忽略上图里的公式,简单解释一下time*10是为了使铃铛摆动的频率更高,*100是为了使铃铛摆动的幅度更大,也就是旋转的角度更大。效果如下:

减法,在公式后面加上一个跟随time变大的减数,比如r=Math.sin(time*10)*100-time*10,随着时间值越来越大,r的值也会越来越小,那不就是我想要的摆动幅度越来越小的效果吗?但事实是r值越来越小却不会停留在0附近,它会变成越来越小的负数,铃铛就会往逆时针方向继续甩下去,如下图:

exp,高等数学里以自然常数e为底的指数函数"百度百科如是说,函数Math.exp(x)等于指数e的x次方,e≈2.7,当我们把x替换成time,就算time为0,用来做分母的Math.exp(time)也不会等于0,同时,用它做除数/分母它的增长是非线性的指数增长,如下图:

用以下表达式,我们终于得到了一条这样的曲线和这样的动画。

r=Math.sin(time*10)*100/(Math.exp(time))

铃铛罩摆动至停止动画

接下来要实现的就是铃铛芯的摆动,跟K帧动画思路一样,同样要对铃铛芯做一个延迟动画,通过观测发现,客观上,在这个60帧/s的合成里,当指针刚走1帧,铃铛罩子"内壁"就已经挨到了铃铛芯,故延时时间可以设为1/60≈0.0167s。但主观上,我为了数字更简洁就再约等于一下,直接写成0.02s,所以铃铛芯最佳的延时时间是0.02s

一个公式可以是一个表达式,但一个表达式却可能包含不止一个公式,AE表达式的编写语言基于JavaScript,所以除了算术运算,还会有逻辑运算。复用罩子摆动的表达式,替换上延迟的时间并作条件判断,芯子的旋转属性下的表达式为:

delay=0.02;//定义铃铛芯开始运动相对于罩子延时0.02sdelay_t=time-delay;//结合上一句,铃铛芯的时间应减去0.02s的时间差if

我在时间大于1秒时强行加大芯子的摆动幅度, amp=time*50+50,这种写法保证时间刚好在1秒时,amp的值仍然是初始值amp=1*50+50=100,这样1秒前后的动画曲线就会顺滑衔接,动画当然就不会出现跳跃。类似的写法还有:amp=time*75+25,甚至直接是amp=time*100,同样能保证1秒处的自然衔接,但是这个芯晃动幅度过大,所以,我决定还是让它缓一点,维持了amp=time*50+50的写法。

elay=0.02;delay_t=time-delay;if (time>delay){         amp=100;         r=Math.sin(delay_t*10)*amp/

铃铛芯优化前后对比。

AI助手