--本篇导航--
如何使用表达式(打开删除,查看图形,错误)
表达式的数组、赋值
输入表达式、优先级
一些常用的表达式(value,time,index,wiggle,random,loopOut,Math,if…else)
表达式控制
一些现成的表达式(可以直接粘贴使用)
如何使用表达式
AE中的表达式通过javascript语句来实现一些效果,比K帧要更高效。
打开表达式
按住Alt的同时点击秒表,可以打开表达式,然后输入内容。
如果有表达式存在时,按Alt点击秒表是删除表达式。也可以直接选中表达式Delete删除。
如果一个图层有表达式,可以连续按下2次E键,快速展开表达式。
不启用/删除表达式
查看表达式图形
默认点击【图表编辑器】图标展示的是关键帧的曲线。
在此基础上,再去点击表达式的波形开关,才会显示出表达式的波形。
有时候在查看其它关键帧曲线时,有其他表达式的曲线,此时,需要去把表达式的曲线显示关掉,就不会干扰了。
表达式错误
如果表达式有错误,AE会检测出来,并提示错误代码的位置。只有无错了,表达式才可以生效。
表达式的数组、赋值
表达式是代码,会有数据结构。
赋值
默认输入就等于属性的值,不需要a=1这种等于(需要注意数据结构要一致)。可以将值或一个表达式赋值给一个变量:var=1;
数据结构
默认一维的数,就是普通的写法。如非3D下的旋转属性。
二维的数,如非3D下的旋转、位置属性。
三维的数,以此类推,就是[var[0],var[1],var[2]]
文字也可以强制设为表达式,是字符串类型。需要用双引号 " " 括起来。
输入表达式
AE中可以手动输入表达式,也可以使用菜单添加。
添加后,有些需要自己手动填写如数值,有些可以直接使用螺旋线去链接已有属性或新建的表达式滑块属性。
表达式关联器,可以跨合成进行连接,也可以跨图层连接不同效果器的属性,还可以连接到某一个属性的不同值,如位置的x,y,z。此时需要锁住目标图层效果器面板,以便拉螺旋线。
有时一些属性值是多维数组,如果只想关联其中某一维度,可以单独出属性值。
优先级
表达式的优先级是最高的。
一些常用的表达式
value
表示当前属性的值,根据属性的维数而定。如一维的旋转,value就是一维的,二维的位置,value就是二维的
value = [value[0],value[1]]
可以加在任何表达式的后面,这样表达式就可以随意修改数值了。
当value为数组时,可以直接和数组形式的表达式相加:
value+[index+200,0];
时间表达式 time
time是1秒,与合成的时间轴长度是一一对应的。后面乘的数值可以看作是换算的旋转度数秒:time*6 (秒针1圈360度,1秒的度数为360/60=6度)分:time*6/60 = time/10时:time*6/60/12
索引表达式 index
获取当前图层在时间轴上的序列号。
抖动表达式 wiggle(freq,amp)
freq:抖动频率/秒amp:抖动幅度(像素)wiggle(freq,amp)是二维数组,默认情况是会影响所有的数组的值,因此获取单个影响值可以使用数组的方式
wiggle(freq,amp)[0],wiggle(freq,amp)[1]
也可以直接使用AE的预设【摆动-位置】来实现
随机表达式 random(m,n)
m:最小边界值n:最大边界值
虽然每个随机表达式的值都是不一样的,但如果想更随机,可以使用seedRandom(随机种子,0/1);随机种子可以写成index,time等false=0 随时间变化而变化true=1 不随时间变化而变化
循环表达式loopOut
是作用在关键帧上的,所以需要先有关键帧,之后再循环关键帧的动画。
loopOut("Cycle") 重头开始循环 A→B,A→B
loopOut("Continue") 在末尾沿着路径一直运动下去
loopOut("PingPong") 往复循环 A→B→A→B 如钟摆
loopOut("Offset") 这一次结束的位置成为下一次运动的起始位置
直接循环属性上的关键帧,循环尽量保持首尾的关键帧数值一致
数学表达式
Math.floor(x),对x向下取整Math.round(x),对x向上取整,也就是四舍五入
Math.sin()往往会与翅膀等运动规律按正弦曲线的动画中使用。数学里的π的表达:Math.PI
给旋转K帧(绕锚点旋转):
Math.sin(time*freq)*angle; // freq是旋转频率,angle是旋转角度
保留小数的位数.value.toFixed(n)
effect("滑块控制")("滑块").value.toFixed(0)
if条件表达式
就是if…else的那些
time = 15;
if (time <= 10) {
"早上好";
} else if (time <= 14) {
"中午好";
} else if (time <= 18) {
"下午好";
} else {
"晚上好";
}
判断可更复杂点
if (2 < time && time < 4) {
90;
} else {
0;
}
表达式控制
属于效果,都是将图层表达式中的一些数链接到表达式控制的滑块(某一个)数值上。
一些现成的表达式
随机循环移动
给位置加表达式
freq = 2; //频率
amp = 500; //振幅
loopTime =3; //循环时间,单位位秒
t = time % loopTime;
wiggle1 = wiggle(freq, amp, 1, 0.5, t);
wiggle2 = wiggle(freq, amp, 1, 0.5, t - loopTime);
linear(t, 0, loopTime, wiggle1, wiggle2)
路径循环表达式
valueAtTime(time%key(numKeys).time)
朝向跟随表达式
function lookAtMe(fromPt, toPt){
lkAt = lookAt(fromPt, toPt);
if(toPt[1] > fromPt[1]){
return 180-lkAt[1];
}else{
return lkAt[1];
}
}
p0 = transform.position;
p1 = thisComp.layer("圆形").transform.position; // 设置目标层名
lookAtMe(p0,p1)+value; // 改变旋转值可调整角度改变
弹性表达式
想要表达式正常工作,就要给最后一个关键帧一个速度值,最后一个关键帧的速度值将会很大程度的影响表达式的抖动效果。当感觉抖动效果不明显时,也可以试试改变一下关键帧速率。最后一帧的速度越大抖动效果越明显。
弹力1
amp=0.1;
freq=2;
decay=2;
n=numKeys;
if(n==0){value;}
else{
t=time-key(n).time;
if (n > 0){
v = velocityAtTime(key(n).time - thisComp.frameDuration/10);
value+v*amp*Math.sin(freq*2*Math.PI*t)/Math.exp(decay*t);
}
else{value};
}
弹力2
amp = 0.4;//幅度
freq = 2.0;// 频率,值越高, 晃地越快
decay = 5.0;// 衰减速度,值越高, 延迟越小
n = 0;
if (numKeys > 0){
n = nearestKey(time).index;
if (key(n).time > time){
n--;
}
}
if (n == 0){
t = 0;
}
else{
t = time - key(n).time;
}
if (n > 0){
v = velocityAtTime(key(n).time - thisComp.frameDuration/10);
value + v*amp*Math.sin(freq*t*2*Math.PI)/Math.exp(decay*t);
}
else{
value;
}
【通过控制滑块控制参数】
amp = effect("amp")("滑块");//幅度
freq = effect("freq")("滑块");// 值越高, 频率越高
decay = effect("decay")("滑块");// 值越高, 延迟越小
n = 0;
if (numKeys > 0){
n = nearestKey(time).index;
if (key(n).time > time){
n--;
}
}
if (n == 0){
t = 0;
}
else{
t = time - key(n).time;
}
if (n > 0){
v = velocityAtTime(key(n).time - thisComp.frameDuration/10);
value + v*amp*Math.sin(freq*t*2*Math.PI)/Math.exp(decay*t);
}
else{
value;
}
弹力3(惯性回弹)
在要设置动画的图层的位置属性中添加关键帧。在该图层的位置属性中添加以下表达式:
// 设置值以控制抖动。
// 将这些值链接到滑块表达式控件以快速预览不同的设置。
var amp = 40;
var freq = 30;
var decay = 50;
// 查找最新的关键帧
var nK = nearestKey(time);
var n = (nK.time <= time) ?nK.index : --nK.index;
var t = (n === 0) ?0 : time - key(n).time;
// 如果当前时间晚于一个关键帧,则计算抖动。
// 反之,则使用原始值。
if ( n > 0 && t < 1 ) {
var v = velocityAtTime( key( n ).time - thisComp.frameDuration /10 );
value + v * amp * .001 * Math.sin(freq * .1 * t * 2 * Math.PI) / Math.exp(decay * .1 * t);
} else {
value;
}
Overshoot(果冻抖动的效果)
freq = 3;
decay = 5;
n = 0;
if (numKeys > 0){
n = nearestKey(time).index;
if (key(n).time > time)
n--;
}
if (n > 0){
t = time - key(n).time;
amp = velocityAtTime(key(n).time - .001);
w = freq*Math.PI*2;
value + amp*(Math.sin(t*w)/Math.exp(decay*t)/w);
}
else
value
Bounce(小球重力下降弹跳)
e = .7;
g = 5000;
nMax = 9;
n = 0;
if (numKeys > 0){
n = nearestKey(time).index;
if (key(n).time > time) n--;
}
if (n > 0){
t = time - key(n).time;
v = -velocityAtTime(key(n).time - .001)*e;
vl = length(v);
if (value instanceof Array){
vu = (vl > 0) ? normalize(v) : [0,0,0];
}
else{
vu = (v < 0) ? -1 : 1;
}
tCur = 0;
segDur = 2*vl/g;
tNext = segDur;
nb = 1; // number of bounces
while (tNext < t && nb <= nMax){
vl *= e;
segDur *= e;
tCur = tNext;
tNext += segDur;
nb++
}
if(nb <= nMax){
delta = t - tCur;
value + vu*delta*(vl - g*delta/2);
}
else{
value
}
}
else
value