1. 一维数值指数变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
if (numKeys >1 && key(numKeys).time > time && key(1).time <= time){
k = nearestKey(time).index;

if (key(k).time <= time) {
a = k;
} else {
a = k-1;
}
b= a+1;
a_val = key(a)[0];
b_val = key(b)[0];
a_time = key(a).time;
b_time = key(b).time;
if(a_val == 0) {
a_val = .1;
}
if (b_val == 0) {
b_val = .1;
}
x = Math.log(b_val) / Math.log(a_val);
exp = linear(time, a_time, b_time, 1, x);
val = Math.pow(a_val, exp);
[val];
}else{
value;
}

只能适用于一维数,需要变化的数值区间必须要大,时间要长,否则看不到效果

2. cycle映射

1
valueAtTime(time%key(numKeys).time)

cycle “pingpong”映射

1
2
t=(time%(2*key(numKeys).time)>=key(numKeys).time)?(key(numKeys).time-time%key(numKeys).time):(time%key(numKeys).time);
valueAtTime(t);

AE中的路径动画无法使用循环表达式,使用这个来实现路径动画的循环

3.位移路径生成形状

1
2
3
4
5
6
7
8
9
10
finalPoint = [];
frameDuration = thisComp.frameDuration;
compDuration = thisComp.duration;
chosenOne = thisComp.layer("the layer name which you want to choose").transform.position;
for(i=0;i<=compDuration/frameDuration;i++)
{
middlePoint = chosenOne.valueAtTime(i*frameDuration);
finalPoint.push(middlePoint);
}
createPath(points = finalPoint, inTangents = [], outTangents = [], isClosed = false);

注意

  1. 这个表达式需要放在形状层Path里面,这个Path一般只有描边没有填充
  2. 需要设置形状层的位置和锚点与目标层的位置相吻合
  3. 这个表达式很容易造成卡顿

4.循环摆动

1
2
3
4
5
6
7
8
9
freq=5; //频率
amp=100; //振幅
octaves=1;//随机噪波
amp_mult=0.5;//细节
loopTime=2;//循环周期
t=time%loopTime;
wiggle1=wiggle(freq,amp,octaves,amp_mult,t);
wiggle2=wiggle(freq,amp,octaves,amp_mult,t-loopTime);
linear(t,0,loopTime,wiggle1,wiggle2);

返回的是wiggle,所以可以用于多维,可以让wiggle重复

5. 颜色随机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//首先需要创建5个滑块
h = effect(1)(1);
s = effect(2)(1);
l = effect(3)(1);
freq = effect(4)(1);
seed = effect(5)(1);
//从名字可以看出,这5个滑块对应hsl、频率和随机种子
seedRandom(seed,true);
//分别给hsl三个属性一个wiggle来随机
H = wiggle(freq,h)[1];
S = wiggle(freq,s)[1];
L = wiggle(freq,l)[1];
//通过调控随机种子,来使这个随机值增加或减少
var plusOrMinus1 = random()<0.5?-1:1;
var plusOrMinus2 = random()<0.5?-1:1;
//原颜色先从rgb模式改成hsl模式
hsl = rgbToHsl(value);
//在hsl模式中加上随机值后转换回rgb模式
hslToRgb(hsl + [H/360*plusOrMinus1,S/100*plusOrMinus2,-L/200,1])
//滑块h属于[0,360] 滑块s属于[0,100] 滑块l属于[0,100]

这个表达式是用在颜色属性上的,拥有颜色属性的图层要添加五个表达式控制滑块

6. 指向目标层

1
2
3
4
lookedLayer = thisComp.layer("lookedLayer");
myLayer = thisLayer;
differencePosition = lookedLayer.transform.position.value - myLayer.transform.position.value;
radiansToDegrees(Math.atan2(differencePosition[1],differencePosition[0]))+90;

这个表达式用在需要指向的图层的旋转属性上,然后填写一个被指向的图层名称

7. 弹性动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
amp = 0.1; //振幅
freq = 2.0; //频率
decay = 2.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;}

经典弹性动画

8.反弹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
elasticity =0.7;//弹力
gravity =1000;//重力
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;
velocityValue = -velocityAtTime(key(n).time - thisComp.frameDuration/100)*elasticity;
velocityLength = length(velocityValue);

if (value instanceof Array){
vu = (velocityLength > 0) ? normalize(velocityValue) : [0,0,0];
}
else{vu = (velocityValue < 0) ? -1 : 1;}

tCur = 0;
segDur = 2*velocityLength/gravity;
tNext = segDur;
bouncesNumber = 1;
while (tNext < t && bouncesNumber <= nMax){
velocityLength *= elasticity;
segDur *= elasticity;
tCur = tNext;
tNext += segDur;
bouncesNumber++;
}

if(bouncesNumber <= nMax){
delta = t - tCur;
value + vu*delta*(velocityLength - gravity*delta/2);
}
else{value;}
}
else value;

模拟重力反弹效果,当然方向随意,一般也是用在位置上

9.弹性晃动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var amp = 2.0; //晃动幅度
var freq = 2.0; //晃动速度
var decay = 4.0; //晃动时间
var maxRotation = 45;//最大角度
var maxSpeed = 3000;//读取的最大速度
var useAxis = 0; // 0使用X轴速度,1使用Y轴速度
var timeBeforeKey = thisComp.frameDuration/10;
var referencePropoty = position;
plusorminus = 1;//1上右端固定或 -1下左端固定

if (referencePropoty.velocity[useAxis] != 0) {
linear(referencePropoty.velocity[useAxis], -maxSpeed,maxSpeed, -plusorminus*maxRotation,plusorminus*maxRotation);
}
else
{
var n = 0;
if (referencePropoty.numKeys > 0) {
n = referencePropoty.nearestKey(time).index;
if (referencePropoty.key(n).time > time) {n--;}
}
if (n == 0) {t = 0;}
else {t = time - referencePropoty.key(n).time;}
if (n > 0 && t < 1) {
var v = referencePropoty.velocityAtTime(referencePropoty.key(n).time - timeBeforeKey)[useAxis];
value -plusorminus* (v*(amp/100)*Math.sin(freq*t*2*Math.PI)/Math.exp(decay*t));
}
else {value;}
}

用在旋转属性上,只能本图层的位置变化才能响应,链接到父级没用

10.四方抖动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
angle =  degreesToRadians(45);
shakeLength = 100;
num = 5;
mode = 0;
modeCase = [];
if(mode==0){modeCase=[0,1,2,3];}
if(mode==1){modeCase=[3,2,1,0];}
if(mode==2){modeCase=[0,2,1,3];}
if(mode==3){modeCase=[0,2,3,1];}

thisDuration = thisComp.frameDuration;
if (thisLayer.marker.numKeys==0){newTime=time;}
else{
markerTime = thisLayer.marker.key(1).time;
newTime = time - markerTime;
}
shakeRatio = 1 - Math.floor(newTime/4/thisDuration)/num;
var plus0 = plus1 = shakeCase = 0;
var shakeCase = Math.round((newTime/thisDuration)%4);

if(shakeCase==modeCase[0]){plus0=-1;plus1=-1;}
if(shakeCase==modeCase[1]){plus0=-1;plus1=1;}
if(shakeCase==modeCase[2]){plus0=1;plus1=1;}
if(shakeCase==modeCase[3]){plus0=1;plus1=-1;}

if(newTime>=4*num*thisDuration||newTime<0){value;}
else{
value + [shakeLength*shakeRatio*Math.sin(angle)*plus0,shakeLength*shakeRatio*Math.cos(angle)*plus1];
}

将物体从四个方向抖动到中间,用在位置属性上,angle指的是每次抖动物体偏移的角度增量,num指抖动次数,mode指抖动模式