欢迎光临散文网 会员登陆 & 注册

【AE表达式】制作windows加载动画

2021-08-19 22:26 作者:Cubx  | 我要投稿



/*表达式文末自取,以下为整体思路*/


分析

很容易看出加载动画是由很多圆跟着一个圆旋转一圈,形成延迟或拖尾的效果;

每个圆的角速度都是慢-快-慢的循环,每经过一次角速度的循环周期,该圆刚好转过360°;

圆的不透明度变化与角速度变化相反


思路

角速度周期变化可以用函数1-cosX解决/*1-cosX恒大于等于0,这意味着圆不会走到一半突然调头跑,它的速度始终为正*/

至于让每经过一次角速度周期刚好转过360°,只需要先通过角速度公式确定角度公式/*根据导数找原函数*/

再使自变量变化一个周期时因变量变化360°

不透明度用linear直接把角速度线性映射过来

延迟效果用 .valueAtTime(time-延迟时间) 很容易实现,但本文选择改变三角函数的相位

//表达式生成动画只需要在一个图层里写表达式,然后ctrl+DDDDDDDDDDDDDD…

//现在你只需要打开AE-按住shift画一个正圆-保存项目-关闭AE就好了


实现

1·确定角速度公式和角度公式之后直接写在形状图层的旋转属性里

角速度公式为1-cosX肯定是不行的

先给它加点参数成为a*(c-b*cosX),注意c>b

//方便之后化简调参

为了确定每个参数对角度变化的影响

把它还原成角度公式a*(c*X-b*sinX)

这个角度公式图像持续向上,符合每个圆持续向一个方向旋转的效果



但该函数周期固定,不便控制,于是引入参数f

将X变为fX

角度公式更改为a*(c*fX-b*sinfX)

角速度公式改为 a*f*(c-b*cosfX),f表示频率

/*凭啥f就表示频率呢,我们先把频率定义为单位时间内转过的圈数

没有f时,X从0增加到单位时间时,刚好转一圈

加上f后,X从0增加到单位时间时,函数中sin()括号里的数实际增加至f倍的单位时间,则因变量增加至f倍,也就是转了f圈

既然单位时间内转了f圈,就认为f表示频率*/

//你想懂?我这下面有些好康的



2·化简消参,使每周期转一圈

f表示频率,则2π/f表示周期

角度公式a*(c*fX-b*sinfX)

//JavaScript里Math.sin()括号里使用弧度值,所以这里周期为2π/f

X=0时,角度为0

X=2π/f时,角度为2π*a*c

则2π*a*c-0=360

//角度公式返回值应为角度制,所以为360°

所以只要满足a*c=180/π,该效果就可以实现


//接下来所有计算都基于a*c=180/π的条件下,即实现每周期转一圈的前提下

我们回到角速度公式a*f*(c-b*cosfX)

探究如何进行速度控制


思路一/*理解简单但不好*/


a*c=180/π代入角速度公式a*f*(c-b*cosfX)得V=f*180/π-a*f*b*cosfX,减号后面是变化量,则可得出

Vmax=f*180/π+a*f*b,Vmin=f*180/π-a*f*b

发现V主要由f控制,而V最大变化差由a*b控制

则可以为控制器图层/*名叫“控制器”的图层,一般用空对象*/添加两个滑块控制,以控制f和a*b,为形状图层的旋转属性输入:

f =3/*自己连接一下滑块控制好吗*/;

ab =60/*只会复制是不行的*/;

X = time;

X*f*180/Math.PI-ab*Math.sin(X*f)

//函数部分:acfx - ab sinfx

//这个方法坏就坏在谁知道a*b什么意思啊,过于抽象



思路二/*控制Vmax/Vmin*/

根据角速度公式a*f*(c-b*cosfX)得出

Vmax=a*f*(c+b),Vmin=a*f*(c-b)

就可以看出Vmax/Vmin=(c+b)/(c-b)=1+2b/(c-b)=1+2/(c/b-1)

于是Vmax/Vmin只与c/b有关,则说明可以用一个参数代替c/b,但c/b的参数含义不便理解,于是选择用k代替Vmax/Vmin

参数k的含义即最低点速度/最高点速度,可得

c=(k+1)/2,b=(k-1)/2进而化简角度公式/*交给表达式做吧*/

同上,输入:

f = 3 ;k = 50 ;X = time;

c = (k+1)/2 ; b = (k-1)/2 ; a=180/Math.PI/c ;

a*( X*f*c-b*Math.sin(X*f)) 

//函数部分:a(cfx -b sinfx)

//你甚至可以把k改为负数



3·不透明度

在最高点使不透明度为100,最低点为0,恰好最高点也是速度最低点,则采用映射

映射分线性映射linear和非线性映射ease,这里用linear

/*linear(映射源,映射源min,映射源max,对象min,对象max)为线性映射,ease为非线性映射,两者参数一致*/

映射即一个量跟着另一个量变化,这里是不透明度跟随角速度变化,则在图层不透明度属性里输入:

linear(

transform.rotation.speed/*获取旋转角度实时变化速率*/,Vmin,Vmax,100,0)

//后来我发现把Vmin和Vmax调换位置并不影响效果,至今不理解

//把100和0位置互换是因为速度最低时不透明度最高

再把上面的公式拿点下来

Vmin=a*f*(c-b),c=(k+1)/2,b=(k-1)/2  可得  Vmin=a*f,则在linear表达式的上方添加:

f = 3 ; k = 50 ;

c = (k+1)/2 ; a = 180/Math.PI/c ;

Vmin = a * f ; Vmax = k * Vmin ;


4·动画延迟

/*valueAtTime的方法你肯定会*/

把代码中的X = time; 改为X = time + s * .001 * index ;

/*time返回时间线所处的时间值,单位:秒;

0.001使调节精度增加;

index返回图层序号,使每个图层延迟量不同;

s * .001 * index 即自变量的延迟量*/

不要忘了为s添加滑块控制

//valueAtTime用于拖尾动画很方便


总结

如果你喜欢的话还可以用表达式控制每个圆的大小、颜色、形状  //过于基础就不讲

一开始做这个动画的参数有f、a、b、c,后来在不断调参的过程中发现参数间的某种联系,就分析代码,最终提炼成两个参数:f和k,于是写下这个表达式基础教程

 

AE初学,大佬轻喷

 

//下面这个表达式动画是我最近一个视频里用到的思路,更基础一点,不知道需不需要出教程



代码/*与上文有一点出入*/

旋转

f=thisComp.layer("控制器").effect("频率")("滑块");

k=thisComp.layer("控制器").effect("最大值/最小值 速度")("滑块");

s=index*.001*thisComp.layer("控制器").effect("偏移")("滑块");

Vmin=1;Vmax=k;c=(k+1)/2;b=(k-1)/2;

//Vmin/af = c - b,Vmax/af = c + b

a=360/(2*c*Math.PI);

//a=360/(2*c*PI),使每一个周期旋转360°

a*(-b*Math.sin((time+s)*f)+(time+s)*f*c)

//函数部分:a(-b sinfx + cfx);导数:af(c - b cosfx)

//V=0.5*af*(k+1-(k-1)cosfx),由导数化简所得

不透明度:

f=thisComp.layer("控制器").effect("频率")("滑块");

k=thisComp.layer("控制器").effect("最大值/最小值 速度")("滑块");

pi=Math.PI;

Vmin=f*360/(k*pi+pi);Vmax=k*Vmin;

//V = 0.5*af*(k+1-(k-1)cosfx),速度公式

//Vmin = af

linear(transform.rotation.speed,Vmin,Vmax,100,0)


【AE表达式】制作windows加载动画的评论 (共 条)

分享到微博请遵守国家法律