前言
这是一篇非编程向、数学向、物理向的技术探讨小文,一切从视觉效果出发,向设计师朋友们介绍如何通过表达式而不需要手动K帧的方式来实现真实细腻的病毒落地反弹动画及橡皮筋回弹动画。请编程高手、数学课代表,物理老师自觉忽略其中不科学、不正统的细节,同时有好的方法也希望不吝赐教,至于我能不能看懂就随缘吧。
正文
疫情在国内得到了较好的控制,却远还没有结束,我们还是要继续保持警惕,警惕病毒反弹。因此作为弹性动画表达式的最后一篇文章,最后一次再蹭病毒的热点,讲讲“反弹动画”实现方式,不过此反弹非彼反弹,纯粹玩个破梗不要方。经过前面两篇的铺垫,这篇也没什么好写的了,那今天先到这儿吧。
图1
开个玩笑,前面有个网友加我微信说我写的AE表达式文章是Ta“唯一能理解且能记住的”,大老远来表示感激,我也挺感激的,让我确切地感受到分享知识这件事情是有意义的,哪怕是像渺小的地球人向外太空发射了那么多卫星、探测器一样,在茫茫宇宙的背景噪声里,它们信号微弱不值一提,但至少我们成功地制造了大量的太空垃圾啊!
一、橡皮筋回弹动画
对,我们今天要讲的垃圾,哦表达式就是前面由前两篇文章引申出来的两个表达式,橡皮筋回弹动画和病毒落地反弹动画,由于橡皮筋回弹动画跟上一篇病毒落水动画用的表达式差别不大,所以就不另起一篇直接写在这里了,先看效果:
图3
如果你上过学就一定像下图那样玩过直尺,不知你们有没有注意到尺子最后振荡的速度会越来越快,直到停下。
图4
橡皮筋回弹到停下其实也是这样一个过程,用科学来解释我也不会,就是观察发现它会越弹越快,这跟铃铛摆动和病毒落水的动画区别就在于此——回弹周期越来越短,频率越来越快。
图5
所以,我们先画一根橡皮筋,再给一个CC Bender特效,固定好橡皮筋的两端,加大Amount值,就能看到橡皮筋产生弯曲变形了,我们将以下表达式赋给Amount属性,就能控制弯曲变形程度的变化,从而实现橡皮筋回弹效果(复制粘贴请看这里):
将下方表达式粘贴到如上图所示位置↑
t=time-0.58;
freq=t*(t+1)*10;
if (time>0.58){
value+-Math.sin(freq)*80/(Math.exp(t))
}
else{value}
其中,t=time-0.58是因为我的示例动画中病毒从高空落到橡皮筋上时时间线正好走了0.58秒,并不是鲁迅还说过:“在表达式中用0.58的人,大抵都是极好的人”,所以橡皮筋在这个时间开始产生变形是没有什么玄机的。
freq=t*(t+1)*10是回弹频率越来越快的终极原因,freq的值会随着t的匀速增大以越来越快的速度变大。而对比我上一篇文章,在病毒落水动画中,正弦函数Math.sin(t*freq)中freq被设定为一个常量,所以回弹的频率和周期是固定的(这里不懂的依然推荐学习高中数学正弦函数部分内容)。
图6
到这里,你也许已经发现了,事实上只要保证“Math.sin()”括号中的值是指数上升,说人话就是变大的速度越来越快就能使回弹频率越来越快,比如填入Math.exp(t)也会有一样的效果,只不过不一定是你想要的效果。
二、病毒落地反弹动画
其实我挺担心触发平台的敏感词过滤的,又是病毒又是反弹的,还担心被一小撮别有用心的人曲解成我在逆着国家大好的抗疫形势说一些危言耸听的话,毕竟现在的网友刷微博都只看几个关键字,就能把“屁股歪”和“阴阳怪气”的帽子到处扣,我真害怕。但我更害怕自己英语还没学好,竟连汉语都不敢讲了。
以上只是吐槽,没有别的意思,上次在“UI某国”发表文章提示我标题里有敏感词,最后我不得不把病毒改成“Virus”才发表出去,我因此相信我们国家本科率只有4%是真的,可能平台假定的逻辑是另外这96%的人不认识“Virus”,这么看来,这是非常有效的信息拦截。
以上依然只是吐槽。
我们来设想一下以下动画的运动曲线:
图7
是不是其实就是把病毒落水动画沉入水面的部分翻转到水面以上,就是病毒落地反弹的动画?小球跳动也是这样的运动形式。我们设定一个条件,当物体的y坐标大于某个值value的时候,就将正线函数曲线走到大于value值的部分的曲线镜像翻转。
图8
如上图中,绿色曲线是上一篇病毒落水弹跳动画曲线,将红线以上部分波峰以红线为轴镜像翻转到红线以下,就有了粉色曲线,粉色曲线就是物体落地反弹的运动曲线,红线就是地面的y轴坐标,也就是上文中说的value值。在本文病毒落地弹跳的案例中,这个值就是病毒位置属性最末关键帧的值。表达式如下(复制粘贴请看这里):
将下方表达式粘贴到如上图所示位置↑
amp=0.1;
freq=6;
v=1;
decay=2.5/v;
a=numKeys;
n=nearestKey(time).index;
et=key(n).time;
t=time-et;
v=velocityAtTime(et-0.01);
p=value+v*amp*Math.sin(t*(t+1)*freq)/Math.exp(t*decay);
q=value+-v*amp*Math.sin(t*(t+1)*freq)/Math.exp(t*decay);
if (t>0 & n>=a){
p;
if (p>=value) {q;}
else{p;}
}
else{value;}
表达式解析在上一篇病毒落水中我已经呕心沥血又是示意图又是流程图地讲解过了,这里我不再逐条展开,关键点在这里“if (p>=value) {q;}”,在上文的定义中,p和q的差别在于q在正弦函数部分“v*amp*Math.sin(t*(t+1)*freq)”前面乘了一个“-1”,就使得value值以上部分被翻转到value轴线以下。快用你的像素眼找找以下两条的区别:
p=value+v*amp*Math.sin(t*(t+1)*freq)/Math.exp(t*decay);
q=value+-v*amp*Math.sin(t*(t+1)*freq)/Math.exp(t*decay);
最后的话
至此,我的弹性表达式存货就都已经奉上了,真的一滴都没有了!
图9
这里再做一个回顾:
一、《从零开始学做表达式动画之——铃铛摆动动画》
https://www.zcool.com.cn/article/ZMTA4OTM5Ng==.html
二、《从零开始学做表达式动画之——病毒落水弹跳动画》
https://www.zcool.com.cn/article/ZMTEyMjU5Mg==.html
三、《从零开始学做表达式动画之——病毒落地反弹动画》
三篇都已经收藏的朋友,恭喜你又多了三篇再也不会看的文章!
老规矩,关注我公众号“好像不明白”,或查看原文,可获取本文全部案例动画AE源文件哦~