AE中的
达式
一、表达式概述
当我们想要创建和链接复杂的动画,却又不想创建许许多多的关键帧时,可使用表达式。表达式很像一个小软件,具体讲像javascript,可以在某个时间点对某个图层的某个属性值进行计算。scripts告诉一个app去做些什么,而表达式是针对属性的。
使用表达式,可以在图层的属性间创建关联、用一个属性的关键帧来动态地对其它图层产生动画….
表达式语言是基于javascript的,但你不必非得掌握javascript才能使用表达式,可用pick whip来链接属性,或拷贝已有的表达式到表达式栏中并加以修改即可。
动画预设也包括表达式,甚至完全是表达式。使用表达式而不是关系帧的动画预设有时被叫作“行为”(behaviors)。
向属性添加了表达式后,可继续为该属性添加或编辑关键帧。表达式可使用由该属性的关键帧生成的值作为它的输入值,然后用该值生成一个新值(即在自身上操作),例如下边的表达式在rotation关键帧动画后又在rotation值上加了90度:
value+90
有些方法—如wiggle---直接对关键帧属性值进行操作(参见属性和方法表达式参考)。
下面的表达式作用于一个图层的位置属性,使得图层位置发生一点点抖动。
wiggle(10,10)
注意:使用wggle表达式比用Wiggler面板要快捷、容易。
对文字进行动画时,可使用Expression selector来指定animator属性对每个字符产生多大的影响,可向同个animator组添加一个或多个Expression selector,该animator组可包含一个或多个属性。
二、添加、编辑和移除表达式
可手动键入、用Expression Language菜单、用pick whip或从其它属性的已有表达式中拷贝来创建表达式。
Expression interface in the Timeline panel in layer bar mode
A. 启用表达式开关
B. 显示 Post-Expression Graph按钮
C. Pick whip
D. Expression Language 菜单
E. 表达式输入框 Expression field
比较常用的做法是用pick whip链接不同的属性,然后运用简单数学运算符对表达式进行适当调整:
+:加、-:减、*:乘、/:除、*-1:对原初执行反操作,例如顺时针及逆时针等。
添加、禁用或移除一个表达式:
(1)添加:在时间轴面板上选择一个属性选择“Animation”菜单Add Expression或按Alt+Shift+=,或按Alt同时点击属性名左边的秒表(关键帧记录器)。
(2)禁用:暂时禁用表达式,点击上图中的A按钮
,禁用时A变为
。
(3)移除:选择有表达式的属性Animation菜单Remove Expression或按Alt同时点击属性名左边的秒表(关键帧记录器)。
编辑用pick whip生成的表达式:
如对javaScript或AE 表达式语言不熟悉,可用pick whip来充分利用表达式的强大功能:从一个属性拖动
到另个属性上,则表达式文本就自动出现在表达式输入框中。
(1)点击生成的表达式,进入文本编辑模式
(2)进行编辑,偶尔使用Expression Language菜单
(3)退出文本编辑模式:按小键盘上的Enter键或在表达式输入框的外边点击鼠标
实例:用expression language菜单创建表达式
(1) 建两个solid层:solid1和solid2
(2) 用关键帧对solid1进行位置动画
(3) 选择solid2的position属性后,选择expression language菜单add expressions或Alt同时点击秒表:则出现默认的表达式---transform.position。
(4) 修改上边生成的表达式为:
thisComp.layer(1).position.valueAtTime(time+2)。
三、显示表达式和表达式曲线图(graph)
在曲线图编辑模式下,单个的表达式输入框变为曲线编辑器底部的一个可调大小的框并只显示已选择属性的表达式。要同时显示出多个表达式,时间轴必须处于图层模式。
四、在Text图层的Source Text属性上写表达式
text图层的Source Text属性的类型是JavaScript String,可用pick whip从另个text图层取得文本,只使用目的层的第一个字符的格式。
关于JavaScript String的更多知识,参考JavaScript书籍。
在字符串中可用 “\r” 来开始一新行文本,例如:把一图层上的文本进行复制并拷贝到该图层上,在另一行显示并变成大写的,用下边代码:
text.sourceText + "\r" + text.sourceText.toUpperCase()
向一个comp添加一个text图层,然后向该图层的source text属性添加表达式经常用来检查其它图层的属性及属性值:
thisComp.layer(index + 1).name + "\rOpacity = " + thisComp.layer(index + 1).opacity.value
下段代码用于报告使用的footage的名字,该footage处于堆栈最上方…
source_footage_name = "";
for (i = 1; i <= thisComp.numLayers; i++){
if (i == index) continue;
my_layer = thisComp.layer(i);
if (! (my_layer.hasVideo && my_layer.active)) continue;
if (time >= my_layer.inPoint && time < my_layer.outPoint){
try{
source_footage_name = my_layer.source.name;
}catch(err1){
source_footage_name = my_layer.name
}
break;
}
}
source_footage_name
五、向表达式添加注释(与Java语法一样)
// :用于添加单行注释
/* */ :用于添加多行注释
六、保存并重用表达式
写好的表达式可拷贝到一个文本编辑软件中进行保存,也可在AE中存作动画预置(animation preset)或模板(template)中。然而,表达式多数时候是针对某个项目编写的,会用到该项目中的具体图层名字等,所以在下次使用时还需进行必要的改动。
可定义自己的方法,JavaScript定义方法的语法见下例:
function average(a, b)
{
return (a + b) / 2;
}
average(position, thisComp.layer(1).position);
注意:必须在表达式中完整定义方法,没有向其中添加方法的全局方法库。
如果想保存一段代码以便可用于其它项目,应该添加注释,也应该使用变量,这样就可在一处改变一个值,而不是在好几个地方去做改动。
例如:
/* This expression on a Source Text property reports the name of a layer and the value of its Opacity property. */
var myLayerIndex = 1; // layer to inspect, initialized to 1, for top layer thisComp.layer(myLayerIndex).name+":\rOpacity="+ thisComp.layer(myLayerIndex).opacity.value
只要表达式中不含有其它项目中没有的属性,就可保存含有表达式的动画预置,之后用于其它项目中。当保存一个没有属性关键帧、只有表达式的预置时,只保存表达式;如果属性还有关键帧,则在保存预置时会连同所有关键帧值一起进行保存。
七、表达式特效控件(Expression Controls effects)
使用表达式特效控件添加一个控件,用这个控件来操纵一个或多个属性的值(通过把属性用表达式链接到控件上),这样一个控件就可影响到几个属性了。
表达式特效控件的名字很直白,看得出它提供何种类型的属性控件,如Angle Control, Checkbox Control, Color Control, Layer Control, Point Control, Slider Control;AE CS5.5 和后来的版本还包括了3D Point Control。
可像使用其它特效那样来使用表达式特效控件:从“特效&预置”面板中拖动对象到图层上。
可向任意图层添加表达式特效控件,然而向一个空图层添加也很有用:这样做就把这个空图层当作控制图层了,然后在其它图层的属性中添加表达式来接受这个控制图层的输入。例如:可向一个空图层添加一个滑块控件,然后把下边的表达式添加到多个图层的Position属性上:
position+[0,10*(index-1)*thisComp.layer("Null ").effect("Slider Control")("Slider")]
效果:调整滑块,其它图层上下动。
对表达式特效控件进行重命名以显示其用处有时是很实用的,例如把一个Color Control effect实例改名为sky color control会用更好的提示性。
注:其它关于特效表达式控件的资源网站
Jerzy Drozda, Jr. (Maltaannon) provides a simple explanation and demonstration of the Angle Control effect and Expression Controls effects in general on the Motionworks website.
Aharon Rabinowitz’s three-part “After Effects Expression Controls” series of video tutorials on the Creative COW website introduces the Expression Controls effects and shows some basic examples of their uses.
Harry Frank provides a clock project on his graymachine website, in which the movements of the hands are connected to an Angle Control effect on a null layer that controls the time.
Todd Kopriva provides instructions for using the sampleImage method and the Point Control effect to monitor colors for a specified point during color correction on his After Effects Region of Interest blog.
八、把表达式转换为关键帧
有时把表达式转换为关键帧很有用,例如:你想冻结一个表达式中的值,则可把该表达式转换成关键帧,然后调整关键帧即可;或者一个表达式需要花较长时间进行计算时,可把该表达式转换成关键帧,这样便可更快渲染。
把表达式转换成关键帧时,AE计算该表达式,在每帧上创建一个关键帧,然后禁用表达式。
转换方法:
在时间轴面板上,选择表达式所在的属性,然后Animation > Keyframe Assistant > Convert Expression To Keyframes。
九、访问属性和方法
用表达式可访问图层的属性和方法,语法是:要访问一个值,使用由点号操作符分隔的对象引用链;要访问一个超出图层属性的值,如特效值、遮罩或文本动画值时,也可使用括号,例如把图层A的透明属性链接到图层B的高斯模糊的模糊属性上,在图层A的透明属性上添加下列代码:
thisComp.layer("Layer B").effect("Gaussian Blur")("Blurriness")
从左读到右,可发现是从高端到低端逐层到达的:
用来引用当前合成的全局对象:thisComp
该合成内的一个具体层用该层的名字来引用:layer(“Layer B”)
该层的一个具体的特效由该特效的名字来引用:effect("Gaussian Blur")
该特效的一个具体特效属性由该特效属性的名字来引用:("Blurriness")
对于多维属性的第n个值,在尾部加上[n],如访问y值:
thisComp.layer("Layer B").effect("Advanced Lightning")("Origin")[1]
一个表达式的默认作用对象就是该表达式所在的属性,所以不必写出属性,因而下边两句等价:
wiggle(5,10)
position.wiggle(5,10)
引用别的图层的,则要写全:
thisComp.layer("Layer A").rotation
十、数组和多维属性
AE中数组是存储一系列顺序化数字(number)的一个类型,由一对儿方括号里边用逗号分隔的数字来表示,如:[13, 5]。
可把数组赋值给一个变量,这样在表达式的其它地方引用该数组就变得容易: myArray=[13, 5];
用数组下标引用数组元素:如myArray[0]指的是13,myArray[1]指的是5。
Dimension
Property
1
Rotation °
Opacity %
2
Scale [x=width, y=height]
Position [x, y]
Anchor Point [x, y]
Audio Levels [left, right]
3
Scale [width, height, depth]
3D Position [x, y, z]
3D Anchor Point [x, y, z]
Orientation [x, y, z]
4
Color [red, green, blue, alpha]
位置坐标这样表示:
position[0]表示位置的x坐标
position[1]表示位置的y坐标
position[2]表示位置的z坐标
颜色用四维数组表示: [ red , green, blue, alpha ]。颜色位深是8位或16位的项目中,颜色数组中的每个元素值取值范围是0-1,比如red为0表示没有红色,为1则全红。所以[0,0,0,0]表示黑色且透明,[1,1,1,1]表白色不透明。对于 32位深的颜色,则允许小于0和大于1的元素值。
数组下标超出数组范围时AE会报错。
想使用position动画的y值,让x值固定为9,可下边这样:
y=position[1];
[9,y];
或者这样更高效:
[9, position[1]]
把图层A的position的x值与图层B的position的y值结合,可这样:
x = thisComp.layer("Layer A").position[0];
y = thisComp.layer("Layer B").position[1];
[x,y]
注意:需说明的情况
(1)一维属性引用多维(多维属性给一维赋值)
此时默认使用的是第一个数组元素值(除非显示指定用哪个值)。例如,如果用pick whip拖动图层A的Rotation属性至图层B的Scale属性,则会生成下列表达式:
thisComp.layer("Layer B").scale[0]
可见,默认使用了scale[0],即scale数组中的第一个元素,也就是宽度维族的值。如果想引用第二个值,则需拖动pick whip至图层B的Scale属性的第二个值上,而不是拖动到属性名上,此时表达式为:
thisComp.layer("Layer B").scale[1]
(2)多维属性引用一维属性(一维属性给多维属性赋值)
AE自动创建一个变量,把一维属性值赋给它,然后用这个变量构建二维或多维属性数组:
如从图层B的Scale属性引用图层A的Rotation属性时,则背后发生:
temp = thisComp.layer(1).transform.rotation; // 读取单值(一维)属性的值,存入变量temp中
[temp, temp]; // 构建匹配数组
十一、矢量/向量(Vectors)
AE中许多属性和方法都接受或返回vectors。当一个数组代表的是空间中的一个点或一个方向时,AE就把它作为Vector来表示。例如AE把position作为Vector来表示。
position是Vector,但audioLevels就不是。尽管audioLevels也是两维数组(左和右),但它表示的不是点或方向。
有些方法的参数是Vectors,但却只有当传入的参数表示方向时才有意义 (即传入“点”position不可),如:cross(vec1, vec2) 。
十二、索引和标签(Indices and labels)
AE中对图层、遮罩和特效的索引是从1开始的,例如时间轴面板中第一个图层为layer(1)。
显然,使用名字而不是索引更好,这样在图层等被调整位置时就不会出错,而且使用名字也可给代码编写者更好的可读性提示。例如下边第一条语句比第二条更易懂:
effect("Colorama").param("Get Phase From")
effect(1).param(2)
十三、时间表达式(Expression time)
表达式中的时间指的总是“合成的时间”,而不是“图层的时间”,而且单位为秒。默认时间是当前表达式正在被计算时的时间。下面两个表达式都使用默认的合成时间,且返回相同的值:
thisComp.layer(1).position
thisComp.layer(1).position.valueAtTime(time)
如果想用相对时间,可在时间参数上加上或减去个值,如:
thisComp.layer(1).position.valueAtTime(time-5) //比当前时间早5秒的那个时间
引用被嵌套的合成的属性的默认时间使用的是原来合成的时间,而不是remapped时间;然而,if you use the source function to retrieve a property, the remapped time is used.
…
十四、错误表达式(Expression error)
如果一个表达式不能被处理,AE就显示一条解释错误的信息并自动禁用该表达式---在表达式左边出现一个黄色的警告标志
,再次点击这个标志可再次看错误信息。
注:要显示哪个表达式出错了,选择一个或多个层,在时间轴面板中右键点击选中的层,从弹出的快捷菜单中选择“Reveal Expression Errors”。
有些表达式使用的是图层或图层属性的名字,此时如果修改了名字,AE会尝试更新表达式来使用修改后的新名字。然而在某些复杂情况下,AE不能自动更新表达式,此种情况下表达式就可能会生成错误信息,需要我们人工更新表达式。