--本篇导航--
-
如何使用表达式(打开删除,查看图形,错误)
-
表达式的数组、赋值
-
输入表达式、优先级
-
一些常用的表达式(value,time,index,wiggle,random,loopOut,Math,if…else)
- 表达式控制
-
一些现成的表达式(可以直接粘贴使用)
如何使用表达式
AE中的表达式通过javascript语句来实现一些效果,比K帧要更高效。
打开表达式
按住Alt的同时点击秒表,可以打开表达式,然后输入内容。
如果有表达式存在时,按Alt点击秒表是删除表达式。也可以直接选中表达式Delete删除。

如果一个图层有表达式,可以连续按下2次E键,快速展开表达式。

不启用/删除表达式


查看表达式图形
默认点击【图表编辑器】图标展示的是关键帧的曲线。
在此基础上,再去点击表达式的波形开关,才会显示出表达式的波形。
有时候在查看其它关键帧曲线时,有其他表达式的曲线,此时,需要去把表达式的曲线显示关掉,就不会干扰了。
表达式错误
如果表达式有错误,AE会检测出来,并提示错误代码的位置。只有无错了,表达式才可以生效。

表达式的数组、赋值
赋值
可以将值或一个表达式赋值给一个变量:var=1;

数据结构




输入表达式




优先级
表达式的优先级是最高的。

一些常用的表达式
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




