-本篇導航--
- 如何使用表達式(打開刪除,查看圖形,錯誤)
- 表達式的數組、賦值
- 輸入表達式、優先級
- 一些常用的表達式(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