当前位置:文档之家› AE表达式

AE表达式

AE表达式
AE表达式

表达式基础

表达式简介

在详细讲解表达式之前,我们先总体了解一下AE中元素之间的关系,据我所知在AE中主要有五种方法建立元素之间的关系:

关键帧:即使元素间没有必然的连接关系,你也可以通过设置关键帧来为它们建立联系。这是最普通的一种连接关系,这种方法也是最灵活的,但是很不利于修改和调试。

合并嵌套:你可以将几个图层一起放置于一个新合成中,这很像其他应用程序中的成组操作,一种将多层素材元素作为单独素材处理设置的方法。

父子连接:不用嵌套为图层建立层级关系的方法,在父子连接关系中任何应用于父层级的变化都会立即影响子层级,而针对子层级的设置不会影响到父层级。

动力学脚本: 像表达式一样,动力学脚本是AE中内置的简单功能,动力学脚本可以为当前图层创建基于另一个图层或属性的关键帧。例如,你可以使用动力学脚本令一个图层模拟另一个图层的位置变化。美中不足的是,使用动力学脚本建立的元素间关系只是暂时的,仅当脚本执行时才会起作用,在后面的设置调整中,针对一个图层的改变不会反映在另一个图连接层上,除非重新应用动力学脚本。

表达式:表达式很类似于动力学脚本,不同的是表达式会保持始终使能,只要应用表达式之后,任何关键帧都会永久保持与之的连接关系。

在这几种连接关系中,表达式的功能最强大,但是学习起来有一定的难度,需要一定的毅力。使用表达式的时机

建立动态连接.正如上面讨论的,使用表达式为图层建立动态连接是一种非常方便高效的方法。

从父层级中仅仅复制一个参数.有些时候,你只想从一个图层中复制一个参数,而不是一整套父子连接图层关系。例如, 在下面的两个动画中,上面的两个图层建立了父子联接,在下面的动画中为黄色图层应用表达式使其只与绿色图层的位置属性建立连接关系。利用父子联接建立的图层关系中子层级会继承父层级的位置与旋转属性,而应用表达式建立的图层关系,黄色图层只会继承绿色层级的位置属性,而其旋转属性由于未被联接到旋转属性,所以该参数不会改变。

无关键帧动画.通过使用表达式你不用设置任何关键帧就可以为参数设置动画。例如, 在下面的这个动画中,图层的缩放属性就是利用表达式中数学正弦曲线来驱动的。

为参数增加随机性.你可以使用表达式为存在的关键帧增加随机性,这种方法非常巧妙,它保留了原始的关键帧设置。当然,AE中内置的摇摆器也可以完成增加随机性效果,但是这种方法会增加很多关键帧,使用表达式建立的随机性效果可以轻松的切换表达式的使能状态,不会影响原始关键帧。

禁用表达式

尽量避免使用表达式.

通常情况下使用其他方法可以实现的效果就不要使用表达式,AE具有强大的工具和功能来实现各种各样的效果。例如,使用父子连接可以实现的效果就不需要再使用表达式。表达式功能的确很强大,但是它不是万能的,而且精心书写表达式后还要维护表达式。

别以为受中拥有了一吧锤子后,世间万物都成了钉子,表达式是一个功能强大的工具,单并不见得就是最好的、最便捷高效的工具。

解析表达式

简单的说表达式就是为特定参数赋予特定值的一条或一组语句,最简单的表达式就是一个数值:

6;

当然了,这种表达式的用处不是很大,常量通过调整参数的值来实现就可以了,像下面这种变量表达式用处会更大:

rotation;

当执行该语句时,AE的表达式会自动计算当前图层当前时间的旋转参数值,返回的值会赋予表达式连接的参数值。如果表达式应用于图层的不透明度属性,那么该图层的不透明度属性会随着旋转属性同步变化,当旋转三十度的时候,图层不透明度也会被设置为30%。

AE中的表达式以Javascript语言(一种用于网站开发的高级通用工业标准程序语言)为基础,Javascript包括一套丰富的语言工具来创建更复杂的表达式,当然包括最基本的数学运算:opacity*10;

这就是一种高级语言,但是十分简单,意思就是当前图层在当前时间的不透明度参数乘以10,因为不透明度参数的值阈是0~100,所以该表达式的之余就是0~1000,该值将赋予表达式连接的任何参数。

等号的位置

也许你认为表达式应该是这种形式,“position=rotation”,AE中的表达式不需要使用等于号将其赋予参数,为参数添加表达式的时候,直接将计算出来的结果赋予参数。当然,你也可以在表达式中使用等于号,为参数赋变量值。

表达式、参数值一一对应

一句表达式控制一个参数,因为一句表达式仅连接在一个参数上,它仅将值赋予该参数。例如,你不可以使用一句表达式来同时修改一个图层的位置和旋转值;你只有创建两个区分开来的关键帧,一个连接到位置属性上,另一个连接到旋转属性上。

多行表达式

表达式可以以多条语句的形式来组织书写,事实上,表达式可以多达上百条语句,但是应该尽量将表达式组织的简捷明了,以使其执行起来高效快捷且便于人们的理解。

当表达式由多条语句组成的时候,最后一行语句所计算出来的值将赋予表达式连接的参数,如下面的表达式:

offset=30;

ralph=rotation+offset;

ralph;

该表达式组将会使图层的旋转值设置为当前时间的旋转值加上30度。

顺便说一句,仔细观察上面的表达式语句你会发觉每条语句以分号结尾。分号清晰的将每一条语句划分开来,从语法上来说,最后一行语句不需要以分号结束,但是如果你习惯的话也可以加上,不会影响语句的执行。

为参数加入表达式

有两种方法为选择的参数加入表达式,一种方法是在时间轴选择参数后,从动画菜单中选择增加表达式;另一种方法是按住ALT键的同时鼠标左键单击参数左边的马表,快速为参数加入表达式。

加入表达式后,你会发现时间轴发生了变化:

首先,在参数名称的左侧多了一个带有“=”的按钮,单击该按钮来切换表达式的使能状态。其次,参数值变为红色,表示该参数由表达式控制,手动编辑该参数将失效。

第三,在参数名称的右边增加了并排的三个图标(稍后讨论)。

最后,在时间轴中增加了一个表达式编辑区域,该区域可以通过下拉箭头来改变显示范围。单击第一个图标按钮会在时间轴窗口中打开表达式的变化图表,从中你可以观察到参数值的变化曲线和参数变化的加速度。如果表达式影响到元素的运动路径,那么合成窗口中显示的路径曲线也会发生变化。

第二个图标按钮是拾取线一个帮助你书写表达式的工具,只需要简单的将拾取线拖动到另一个参数上面,就可以为当前参数与拾取的参数建立动态连接关系,在后面的教程中详细讲解拾取线的功能。

第三个标按钮是表达式结构下拉菜单,使用该菜单可以方便的参考AE的表达式语言,使用该菜单可以清晰的看到表达式所影响的属性和元素。

拾取线

使用拾取线可以方便的建立参数间的连接表达式:

例如,为图层的不透明度添加表达式,然后拖动拾取线到图层旋转参数上就会为不透明度与

旋转参数建立动态连接,现在再为旋转参数设置关键帧,会同步影响到不透明度属性:

如果你将拾取线拖动到同一合成不同图层的属性参数上,那么AE就会创建一个稍微复杂一点的表达式,表明与哪一个图层的属性建立动连接:

this_https://www.doczj.com/doc/3c15415877.html,yer("Solid 1").opacity

这个表达式首先指明合成("this_comp"),然后指明该合成中的图层("solid1"),最后指明该图层被用于建立连接的属性(opacity)。AE会精确的设置建立连接的合成与图层,应该熟记AE的这种语法结构。

顺便说一句,拾取线没有什么特别神奇的地方,可以说它仅仅起到一个打字机的作用,自动将连接的属性名称极其所属合成与图层添加到表达式文本区。你也可以亲自手写表达式,但是这种方式远远不及拾取线方便准确,特别是当需要编写较复杂的表达式时,拾取线的高效快捷更是体现的淋漓尽致。

向量、阵列、维数、索引

有时候你会发现通过拾取线创建的表达式看上去好象在重复参数,例如,如果你将位置参数的拾取线拖动到旋转参数上,你就会得到如下表式:

[rotation, rotation];

因为位置属性有两个参数(X、Y坐标)而旋转属性只有一个参数,建立连接关系后,表达式自动将旋转参数应用两次分别位置属性的X、Y坐标参数。

由两个或三个数值来描述属性的参数组叫做向量或阵列,AE中很多的属性参数是向量式的,包括位置、轴心点和缩放等属性;

阵列对应的用单个数值来描述属性的参数叫做标量式参数。

1、向量与阵列

究竟向量和阵列之间有什么区别呢,你也许会注意到AE的帮助文件有时候互用这两个单词,简单的说向量是既有大小又有方向的数字阵列,其运算结果即要考虑到大小又要考虑到方向;阵列是一套独立元素的组合,阵列中可以包含任何元素,可以是物体阵列,词汇阵列或者是混合阵列:

ralph=[10, this_layer, "bob"];

也许没有人会知道上面的这种阵列会有什么用处,但是它确实是一个正确的阵列,当然在AE中我们大部分时间内遇到的是数字阵列(也叫向量),因为其他类型的阵列在AE中没有用。所以,在接下来的描述中,当谈论到通用的概念和操作应用时,我们使用阵列来描述;当涉及到特殊的数字阵列时我们用向量来描述。

索引

对于阵列来说,你可以使用阵列名加上包含数字的中括号从阵列中提取需要的单一元素,例如:

position[0];

这种表达方法叫做索引,注意在阵列中使用索引调用元素时,必须从0开始计数第一个元素,也就是说,阵列中的第一个元素必须以阵列名加上[0]来表示,第二个元素必须以阵列名加上[1]来表示,依次类推。

所以,上面的表达式就返回位置属性向量中的第一个参数——x坐标,那么position[1]就返回位置属性中的Y坐标,千万不要搞混淆了,在AE中虽然所的调整都是从1开始的,但是当使用索引时,必须从零开始计数

建立阵列

如果要建立阵列,可以将数值以逗号分隔开放入中括号中:

my_vector=[10,20,30];

该表达式的意思是将一个三维数组赋予变量my_vector,该数组中包含三个元素分别是10,20,30,.

my_vector[1];

该表达式计算得出的值是20(数组中的第二个元素)。

维数

阵列中的元素个数代表阵列的维数,例如上面的my_vector是一个三维数组,位置属性是一个二维数组或三维数组(转变为三维图层)。标量式的属性如旋转和不透明度属于一维参数(准确说单一数字或者是标量数值就是一维向量)。

需要注意的是诸如位置属性这样的多维数组或者是自定义的数组变量,不需要将他们的名字写在方括号中,AE会将其识别为数组。当要索引阵列或者是描述阵列时,需要使用方括号。修改阵列中的一个元素

可以用如下的方式来书写位置表达式:

[position[0], position[1]];

将位置阵列中的两个参数分别提出来后,再将他们放入同一个阵列中,看上去与仅仅书写positon的结果相同,优点是你可以使用这种结构来修改阵列中的一个元素而不影响另外元素,例如:

top_of_layer=0;

[anchor_point[0], top_of_layer];

在这个表达式中,阵列中的第一个元素是轴心点的X坐标值,第二个元素是0,如果将该值赋予轴心点属性,那么轴心点的X值将受AE的控制调整,而轴心点的Y值将始终为0。

当使用这种结构时要特别注意,如果将图层设置为3d图层,就需要重新书写表达式,将位置与轴心点Z轴考虑进去。

例如,如果仍然使用上面轴心点的例子,但是这次将轴心点所在的图层设置为3D图层,AE 会自动将丢失的Z轴坐标设置为0,这当然比出现程序错误要强的多,但是所得到的结果未必是我们需要的,因为表达式将忽略轴心点的Z轴坐标的变化。

再看另外一个例子,假如你将一个图层的位置属性复制到另外一个图层上,并且将该参数的Y轴值减去100:

ralph=this_https://www.doczj.com/doc/3c15415877.html,yer(1)

[ralph.position[0], ralph.position[1]-100];

如果这时将图层设置为3D图层,你会发现对控制图层的Z轴所做的任何操作丝毫不会影响到受控图层的Z轴,因为表达式中没有表明Z轴的坐标值,AE会自动将其设置为0。

阵列的重要性

为什么用如此大量的篇幅来描述阵列呢,因为在你所书写的表达式中必须提供正确的参数维数,例如仅仅给位置属性提供一个参数就是错误的

position=6;? // ?? 不正确

这条语句就是错误的,因为位置属性至少需要两个参数:

position=[320,240]; // 正确

顺便提醒一句,你完全没有必要写成这种形式“position=”,因为在书写表达式时就已经将该

值赋予了连接的属性参数。

如果你所书写的表达式存在错误,书写完毕后AE会自动弹出一个错误对话框同时该表达式将被禁用。

如果要避免这种错误,你需要核实正确的参数维数,, 可以通过AE自带的帮助文档或教程后面提供的参考表格来查阅表格.

同样的如果在表达式中涉及到另外的参数,你也需要在帮助文档或者是下面的表格中查阅参数维数,你需要调整来自这些参数的值以匹配你所需要的输出维数。如果你引入了一个二维参数到一个一维数组中,你就需要调整维数以适应输出(如忽略二维数组中的一维元素)。下面的表格中列出了AE中大部分属性参数的维数以及这些参数值的范围:

当使用拾取线时,AE会自动通过索引向量(一维——二维)或重复标量(二维——一维)的方式矫正维数的匹配。

参数值范围

当使用表达式中的拾取线来建立参数之间的关系时,AE会自动纠正由于错误的维数匹配导致的错误,但是这种纠正之后的表达式并不意味着就是你所需要的,物理错误是避免了,但是逻辑错误仍然会影响你的创作。.

在这里特别强调一下,有时候你需要调整当前参数值以匹配目标参数。例如,在前面的例子

中我们使用图层的旋转属性来控制图层的不透明度属性,你会发现当旋转属性达到100度时,不透明度属性就达到了上限,但是我们想要的效果是当图层完成一个周期的旋转时其不透明度,我们就需要调整参数范围以达到我们的需要。

缩放参数范围值的方法很简单,可以利用公式(当前连接参数/当前连接参数范围上限=目标连接参数/目标连接参数范围上限),还是使用上面的例子来说明,我们需要将旋转参数的范围(0~360)缩放到不透明度参数的范围(0~100),所以我们就需要为不透明度加上表达式:

rotation / 360 * 100

从而就达到了我们需要的效果,不透明度在0~360度范围内变化:

使用这个简单的小技巧可以完成很多期望的效果。例如,使用一个轮胎的素材作为图层,我们就可以利用该图层的位置属性来驱动图层的旋转属性,我们只需缩放位置属性来为旋转属性建立正确的连接表达式,因为轮胎每旋转360度就会移动一个周长的距离,所以我们应该这样书写表达式:

rotation=distance/circumference*360:

在这里distance代表图层的运动距离,circumference代表轮胎的周长,但是我们怎样将这个公式转化为AE能识别的表达式语句呢?与前面的旋转不透明度的例子比较这个方程式好象发生了本质的变化,但是事实不是这样的。

开始我们提到了我们是要使用这个表达式,让图层的位置属性来控制图层的旋转属性——模拟真实的轮胎行进动画。但是位置属性真的能正确控制旋转属性么,或者说旋转属性能准确的控制位置属性么?答案当然是否定的,你可以试着使用拾取线让位置属性驱动旋转属性,为位置属性设置关键帧,再观察旋转属性,虽然有所变化但根本不是我们需要的效果。

因为我们的轮胎只会在水平方向上滚动,位置属性中的X轴参数(还记得二维数组么),也就是position[0]来计算轮胎移动的距离;它将从合成窗口的最左(X轴方向的0点)边开始运动,随着向合成窗口的右侧移动,X值会慢慢增大。(AE的坐标原点位于合成窗口的左上角)

前面我们提到过,轮胎行进的距离为一个周长的时候旋转的角度正好为360度,否则这个轮胎就会出现在地面上滑行的现象,所以我们使用上面提到的公式,轮胎的周长是当前连接参数范围上限,360度是目标连接参数范围上限,所以正确的方程式为:

rotation=position[0]/circumference*360

当然了轮胎不可能只行进一个周长的距离只完成一周旋转,换句话说周长与360度不是理论意义上的范围上限,但是不用担心,我们的表达式只是起到为范围之间的转换建立一个比例系数的作用,真正的范围要由计算得来。

接下来我们需要定义轮胎的周长,圆的周长应该等于圆周率派乘以圆的直径(c=2*R*PI):

我们可以使用图层的宽度作为轮胎的直径(理论上讲,轮胎的直径无限趋近于图层的宽度),

而Javacript内置的PI值精确度非常的高,我们可以使用函数'Math.PI'来计算PI值,(当然,也可以直接粗略写成3.14作为PI值)这样周长的表达式为:

circumference=width*Math.PI;

最后我们可以从表达式中删除'rotation=' ,我们前面提到过,计算得出的值会自动赋予加入表达式的参数。当将这些语句组织起来的时候我们就得到了最终的表达式:

distance=position[0];

circumference=width*Math.PI;

distance/circumference*360;

留给读者一个小练习,试着使用图层的缩放属性来控制旋转属性,哈哈,其实很简单,自己动动脑筋吧!

下面这个特殊旋转效果你能利用所学知识完成么:

也许有人会问,为什么要花费这么大的经历来讲解参数范围呢,通过为旋转和位置属性设置同步关键帧不是同样可以完成这种真实的效果么。对于匀速运动的图层来说设置关键帧确实可以达到这种效果,但是如果是模拟变速运动利用这种设置关键帧的方法就会出现图层在地面上滑动的状况,手动设置变速运动非常困难,但是使用表达式就方便多了。

插值方法:线性liner(),平滑ease()

我们已经学习了怎样利用表达式来缩放参数值的范围,只需要简单的乘除运算就可以了---例如将旋转参数范围(0~360)缩放到不透明度参数范围(0~100),但是这不是唯一的方法,AE提供了一套内置的插值算法进行参数之间的转换:

linear(t, t_min, t_max, value1, value2)

ease(t, t_min, t_max, value1, value2)

ease_in(...), ease_out(...)

这些语句看起来很复杂,因为语句中包含很多参数:

t 当前参数,例如旋转参数,不透明度参数或者是你所选择的其他变量,该参数必须是一维的,该参数为必选参数。

t_min当前参数范围的下限,该参数为可选参数,如果参数范围的下限或上限被忽略掉了,那么AE会将参数的范围定义在0~1之间。

t_max当前参数范围的上限,该参数为可选参数。

value1目标参数范围下限,当t≤t_min时,表达式返回该值,该值几可以是一维标量也可以是二维向量,与value1的维数相同,该参数为必选参数。

value2目标参数范围上限,当t≥t_max时,表达式返回该值,该值几可以是一维标量也可以是二维向量,但是如果该值与value1 的维数不同,AE会自动以value1 值为标准进行匹配,该参数为必选参数。

通过下面的例子让我们来了解一下该语句的含义:

linear(time, 0, 5, 0, 360);

通过上面的学习,我们应该将这个语句理解为,时间的变化范围是0到5,目标参数的范围是0到360,整个变化过程是线性的。如果将该表达式应用到图层的旋转属性上,那么你会发现图层在前5秒内完成了一周的旋转。

应用该表达式后,图层在第五秒停止旋转,这就是与我们前面介绍的直接手写公式

time/5*360最大的区别,插值算法自动在当前参数与目标参数之间采样范围极值。

另外一个区别就是你可以设置不同的插值算法:ease(),ease_in()和ease_out()。这些插值算法与同名的关键帧插值算法(通过关键帧助手菜单设置)的作用相同。利用这些插值算法可以为数值转换计算提供一个更自然的运算过程,从而得到更流畅的变化效果,仅仅使用前面介绍的手写公式是做不到这一点的。

看看下面的动画,体会一下不同的插值算法(所有的图层使用相同的参数,只是插值算法不一样):

示例: 滚动栏

现在让我们使用这种简单的方法来快速完成一个例子,我们将制作一个滚动栏的动画。首先我们需要建立两个图层,一个文本区域图层和一个滚动栏图层。我们要为文本图层的轴心点加入表达式,因为这样可以保证我们可以操纵图层的位置属性(当图层滚动时位置属性仍然不会改变)。

记住一定要在一个方向上控制轴心点以得到正确的滚动效果,在这个例子中我们将对轴心点做垂直方向的运动以使文本区在合成窗口中上下滚动。为了使滚动的范围最大,也就是文本区域全部实现滚动,我们将轴心点的Y值范围设置为0到图层的高度,也就是我们的目标参数值为:

value1=0

value2=height

至于当前参数范围,我们将其设置在到合成窗口的高度之间,我们需要在顶部与底部空出几行以得到更好的效果。假如合成窗口的尺寸为320×240,那么就将当前参数范围设置在25至215之间,当滚动栏在Y轴上从25运动到215时,文本区将开始滚动。

t_min=20

t_max=220

当然,当前参数就是滚动栏的Y轴坐标:

t=this_https://www.doczj.com/doc/3c15415877.html,yer("Scroll").position[1]

将几条语句综合起来,加以恰当的变量名称,我们就得到了下面的表达式:

scroll_y=this_https://www.doczj.com/doc/3c15415877.html,yer("Scroll").position[1];

scrolled_amount=linear(scroll_y, 20, 220, 0, height);

最后我们将scrolled_amount的值放到一个二维数组中,让文本图层的轴心点X轴坐标保持不变,最终的表达式为:

scroll_y=this_https://www.doczj.com/doc/3c15415877.html,yer("Scroll").position[1];

scrolled_amount=linear(scroll_y, 20, 220, 0, height);

[anchor_point[0], scrolled_amount];

最后效果如下(只为滚动栏Y轴的位置属性设置关键帧):

上面的表达式只要稍加改动就可以实现水平滚动的效果,如果将该表达式应用到3D图层的旋转属性上,就可以制作出三维滚动旋转效果:

缓存参考对象

前面的教程中我们已经讲解了如何使用拾取线来建立简单的表达式,有时候你不想也不能通过这种方式来建立表达式。例如,你不可以将拾取线拖动到屏幕中不可见的参数上(图层宽度或者是持续时间等)。

在这种情况下,你就需要建立一个缓存参考对象,这要比使用拾取线复杂的多,因为你需要理解一些Javascript的语法,刚接触到这种方法时也许会感到很困难,一旦我们理解了一些术语后,我们就会感受到建立参考对象的方便之处。

对象

简单的说对象就是一个容器,每一个对象都可以包含其他的对象、属性和方法。

例如,AE中的一个合成就是一类物体,每一个合成中都可以包含有其他的对象,像图层或者诸如持续时间和宽度等属性(我们在后面讨论)AE中的所有元素对于我们来说都是很熟悉的——合成、图层、不透明度等等,他们或者属于对象或者属于对象包含的物体。

因为对象可以包含其他的对象,所以说对象存在层级结构,位于最高层级上面的对象叫做全局对象。

全局对象和非全局对象

要标识需要从中提取数据的属性,必须首先标定一个全局对象。

全局对象在AE的表达式中不需要作出任何的特定说明具有唯一的指向作用,其他的对象均隶属于全局对象也就是所说的非全局对象,要想指向特定的非全局对象,必须首先在其前面加上所在的全局对象名称。

还没有理解,没关系,我们用街道地址来做一个比喻,如果要邮寄一封信件,仅将收信人地址写成92号的话邮递服务部门就会十分迷茫,因为在全国可能有数十万个92号的门牌,而你所说的究竟是哪一个呢?所以说你至少要在地址前面加上省份、城市、地区和街道,如果你在海外还需要注明国家,至于国家的上一级就没什么说明的意义了——任何国家均在地球上是人人皆知的,那么国家就是全局对象。

因此,在AE中,在任何制作前你需要建立一个全局对象,就像你需要在信封上面注明收信

What’s in an Object?

确定了全局对象后,我们就需要设置属于该对象的次级物体、属性或者是方法,但是你又怎么知道你所选择的属性或者是方法什么意思呢?可以参见AE用户手册中的表达式部分来进行参考设置。

首先你需要明确对象的类型,例如,"this_comp"就会返回合成对象,然后你就可以在参考表格或用户手册中查找该类对象所包含的属性、方法或者是次级物体。在下面的例子中,我们可以看到在合成对象中可以包含图层对象还有图层宽度或持续时间等属性。(还有很多其他属性).

所以,设置完全局对象后,我们可以在当前合成中选择一个特殊图层:

this_https://www.doczj.com/doc/3c15415877.html,yer("Solid 1")

该表达式返回当前合成中叫做“solid1”的图层,如果我们仅仅需要一个图层次级对象,那么到此就可以结束了,如果我们还需要该图层的属性或者是事件就需要在该语句后面加上相应的参数。

让我们再来看一下语句的书写方式,javascript语法规定全局对象与次级对象之间必须以点号分割,以说明物体之间的层次关系。

另外,在整条语句中,除了引号中间图层名称之间可以加入空格外,期于地方不允许出现空格。.

既然我们已经确定了图层次级对象,再来加上图层的方法属性,例如:

this_https://www.doczj.com/doc/3c15415877.html,yer("Solid 1").opacity

在这个语句中,电号再次起到分割次级对象与属性的作用。

如果你仍然感到这个语法十分麻烦,那么你还可以使用拾取线来帮助你,在表达式区域使用鼠标选中需要物体参数参考连接的部分使其高显示,亮然后拖动鼠标到需要建立连接的参数上,AE将自动插入正确的对象参考连接,你也可以拖动拾取线到其他的窗口上面,甚至包括项目窗口。

除了我们前面列出的属性外,图层还包括下面的属性和方法:

这个表格不是十分详细–要参看详细的表格单击这里也可以查阅AE的用户手册. 这里的表格仅仅证实图层的属性可以返回给不同对象, 甚至包括其他合成. 例如你可以建立下面的表达式:

this_https://www.doczj.com/doc/3c15415877.html,yer("Nested Comp")https://www.doczj.com/doc/3c15415877.html,yer("Solid 1").position

默认对象——当前图层

图层参考语句看起来十分烦琐,也不便于记忆,AE提供了默认的对象以简化最通用的参考对象:this_layer,如果不设置任何全局对象,AE会自动理解为针对当前图层,并且所有的操作都从当前图层开始。这就是你可以只写"pacity"而不必书写"his_layer.opacity"的原因。

如果还没有理解默认对象的话,回忆一下我们前面讲到的地址邮信的例子,当你身处大陆并且需要往大陆邮信时,你可以不用在地址前面加上国家的名字,邮政服务部门也可以很好的为你服务,在这里,中国就是我们所说的默认对象。在AE中,如果不特别指明全局对象,表达式就会使用默认对象, ‘this_layer’.

当然, 如果你需要指明当前图层以外的对象, 你就需要设置适当的全局对象.

即使你想选择当前合成中的另外的图层, 你业不能写成这种形式‘layer("Layer 1")’ 因为图层不是全局对象–他们是属于合成的次级对象, AE需要知道图层所在的合成. 所以你需要在图层前面加上合成名字:

this_https://www.doczj.com/doc/3c15415877.html,yer("Layer 1")

记住这种结构—你会在今后的制作过程中频繁的使用他.

方法与属性

在前面的教程中我们讨论到了对象以及他们所包含的内容和方法,你也许会提出疑问,什么是"方法"呢?

别担心,下面我们来简单讨论一下"方法"。

你不需要理解“方法”究竟是什么,也不需要区分方法与属性之间的区别,因为这些都不重要。你需要知道的是当前对象的可选属性和方法都包括哪些。(因为方法与属性都隶属于对象,所以首先你需要设置对象)

如果你就是对二者之间的区别充满好奇的话,简单的说属性就是事件,方法就是完成事件的途径,属性是名词那么方法就是动词,这里面有一个技巧可以帮助你识别当前正在处理的是属性还是方法,通常在方法后面会有一个小括号,提供一些格外的信息,例如:

this_layer.opacity.value_at_time(0)

‘Value_at_time()’ 就是一种方法,该语句的返回值就是当前图层在括号内表示的时间下的不透明度属性值。

矢量运算

由于Javascript的一些限制,我们不能对矢量参数值使用一些诸如+,-,*,/的标准数学运算符号,我们需要使用特殊的矢量运算方法:

add(vector1, vector2)

sub(vector1, vector2)

mul(vector1, number)

div(vector1, number)

这就意味着矢量算法看上去很难理解阅读,例如一个简单的运算:

(a-b)/2

就会变成

div(sub(a,b),2);

很明显后者的格式比前者复杂的多,也不便于书写,也将书写表达式的错误几率提高,我们的宗旨是使用最通俗易懂的语句来高效完成制作。这样看来矢量运算存在一定的不便之处

一个最好的解决办法就是将复杂的操作分开来书写,还是用上面的例子来说明,我们可以将它这样拆开:

temp=sub(a,b);

div(temp,2);

这种方法看起来简单的多了,也降低了出错的几率,因此我们推荐在书写复杂的矢量运算表达式时,将其分开书写,每一句只包含一个运算。

实例应用

在第一部分的最后,我们将使用前面介绍的表达式基础部分的知识来完成一个简单的小例子。我们将重新使用轮胎的例子,使用移动属性来控制图层的旋转属性。

首先,让我们整理一下制作思路,我们要给图层的旋转属性加上表达式,并在表达式的最后以一个标量结束,所以首先要给旋转参数加上一个表达式。

接下来,我们需要给图层的位置属性设置关键帧,以为位置属性的变化将会驱动旋转属性的变化,在我们的例子中,我们仅仅需要轮胎在X 轴上移动,所以我们只需要:

position[0]

真实的物理世界告诉我们当轮胎移动一个周长的距离时,它将完成一个周期(360)的旋转,在开始时我们会为设置计算公式而犯愁,还需要知道,轮胎的尺寸会影响到在一个旋转周期内其移动的距离,所以我们需要了解轮胎的尺寸,图层的宽度。

假如轮胎的尺寸与图层的尺寸相差无几(在轮胎的周围没有空白的区域),我们可以使用图层宽度来描述轮胎的直径:

width;

但是我们不能直接使用图层宽度,我们需要使用图层宽度来计算出轮胎的周长,利用基本的几何学公式我们就可以计算出轮胎的周长,Javascript为我们提供了一个精确的PI值,所以我们就可以这样来计算轮胎的周长:

circumference=width*Math.PI;

如果轮胎的宽度是100个像素,他的周长将会是314个像素,但是如果我们改变图层缩放属性呢,再使用图层的宽度来计算轮胎的周长所得到的结果就不会准确,为了得到更准确的计算结果,我们要利用图层X轴向的缩放属性来控制轮胎的周长:

circumference=width*( scale[0]/100)*Math.PI;

我们将图层的X轴缩放属性(scale[0])除以100是因为缩放属性的返回值是百分比,

接下来我们就需要定义图层在X轴向移动的变量,在我们的例子中我们要使图层从X轴的零点开始移动,所以我们使用下面的表达式:

distance=position[0];

最后我们写出核心表达式:

(distance/circumference)*360;

该表达式的含义前面已经介绍过,这里就不详细说明了,综合起来,我们需要给旋转属性赋予这样的表达式:

circumference=width*( scale[0]/100)*Math.PI;

distance=position[0];

(distance/circumference)*360

这时再观看动画,会看到轮胎的移动与旋转已经非常的自然了,丝毫没有滑动的痕迹,还是那句话我们可以使用手动设置关键帧来实现同样的效果,但是如果图层作加速减速运动时,表达式的优势更是体现的淋漓尽致。

可以将这种方法应用到单独的文字动画中,也可以应用到非正常运动的物体中,得到真实的效果。

表达式深入

AE几何学概述

在表达式基础部分的讲解里,我们涉及到的大部分是一些代数学的应用,在AE的表达式中只需要应用简单的代数学知识就可以实现很多效果,但是如果在书写表达式的时候融入几何学知识,那么表达式的高效便捷将体现的更加淋漓尽致。简单的说,几何学就是研究图形的空间关系的自然科学。在接下来的教程中我们将讲解一些基本的几何学公式和关系函数以及几何学在AE表达式中的应用。

这部分教程结构组织得非常严谨,当你完成这部分教程的学习时,你就能基本掌握几何学知识的实际应用,例如建立位移属性与角度属性之间的关系,进而生成和谐的运动状态。

矢量运算——矢量加法与矢量减法

也许你会问,我们为什么要将数字阵列称为矢量呢,难道说矢量就是阵列,还是说矢量就是像Illustrator或Flash这类软件制作的动画或静帧素材?

通常我们使用在网格上标记点的方法来表现数字阵列。例如,矢量[80,60]就可以在二维网格上显示为:

更准确的说,[80,60]描述了从[0,0]到[80,60]的矢量,同时指明了方向和大小,在上面显示

为一个白色箭头——水平方向移动80个单位,垂直方向移动60个单位。而对于三维阵列来说,我们就要用三维矢量来描述:

那么,我们为什么把[80,60]表示为矢量而不表示为一个该矢量指向的点呢?原因是当我们把一个点从他所属的线或者是面中提取出来的时候,这个点就变的毫无意义,一个点无法与其他的点区分开来——他们仅仅是孤立的点,因此就无法正确的描述一个矢量。

换句话说,矢量包含有自己的属性,矢量既有大小也有方向。这样看来,[80,60]与[20,30]就是截然不同的两组阵列。

所以说,每个数字阵列定义一个矢量,数字阵列就是矢量。

矢量加法

很明显当我们将两个矢量进行加法运算时,只要对阵列中相应的元素进行运算就行了: [20,70] + [60, -10] = [80, 60]

我们可以用图形的方式来表现这种加法:

通过上面的例子我们可以看出,每个矢量都可以拆分成若干组矢量的组合形式来表示,例如:[80, 60] = [80,0] + [0, 60]

当用图形来表示上面的矢量加法时,矢量之间的关系组成了一个直角三角形:

稍后我们将对AE中的矢量属性应用这种方法,在三角形的运算中我们还将使用到勾股定理。矢量减法

同矢量加法一样,将两个矢量相减时,只要分别对矢量中的元素应用减法运算就可以了: [80, 60] - [20, 70] = [60, -10]

减区一个矢量相当于加上该矢量的相反数:

-[c, d]= [-c,-d]

我们可以使用下面的图形来表示矢量减法:

通过上面的图形示例我们可以看出,我们可以对两个矢量图层进行减法运算来找出这两个图层之间的矢量,这两个图层之间的距离就是运算后得到的矢量的长度。

在下面的章节中我们将讨论计算矢量长度的技巧。

距离——勾股定理,length()函数

我们有不同的理由需要测量两点之间的距离——例如,书写一个跨度计算脚本或创建邻近效应。正如我们前面讨论的,要计算两点之间线段的距离,我们只需对两点的对应的矢量进行减法运算,运算后所得到的矢量的长度就是两点之间的距离。

在AE中,有两种计算矢量长度的方法,一种是复杂方法,另外一种是简单方法。首先让我们了解一下复杂方法:

勾股定理

还记得我们中学几何中学习的勾股定理吧,在该定理中规定了,直角三角形中斜边的平方等于两个直角边的平方和:

在前面的教程中我们提到过,任何一个二维矢量都可以组成一个直角三角形,所以我们可以使用勾股定理来计算任意两点之间的线段长度。首先我们通过计算来找到表示两点之间线段的矢量,然后将它分离出来,最后使用勾股定理就可以计算出这条线段的长度。

根据Javascript语法对表达式的规定,我们需要书写下面的表达式来完成上面的计算过程:// 拾取两点

point1=this_https://www.doczj.com/doc/3c15415877.html,yer("A").position;

point2=this_https://www.doczj.com/doc/3c15415877.html,yer("B").position;

// 计算出两点之间的矢量

delta=sub(point1, point2);

X=delta[0];

Y=delta[1];

// 计算矢量长度

distance=Math.sqrt(X*X+Y*Y);

不是很复杂是么,但是还有一个更简单的方法。

length(vector)

在AE表示式中内置了一个函数来计算矢量的长度:length()函数。将该函数应用到任何维数的矢量中就会返回矢量的长度,

使用length()函数,我们可以重新书写上面的表达式:

// 拾取图层

point1=this_https://www.doczj.com/doc/3c15415877.html,yer("A").position;

point2=this_https://www.doczj.com/doc/3c15415877.html,yer("B").position;

// 计算出两点之间的矢量

delta=sub(point1, point2);

// 计算矢量长度

length(delta);

使用这种方法不仅书写简便而且理解记忆起来要比使用勾股定理要简便得多。这种方法还有一个优点就是可以计算出任何维数矢量的长度,我们也可以将勾股定理应用到三维图矢量中,但是非常麻烦。

实例应用:交互模糊

说了这么多,这种计算方法究竟可以应用到什么地方呢?一个最明显的应用就是应用这种方法来控制图层或者是效果参数。在下面的例子中,我们将使用前面提到过的插值算法首先将距离值范围重新设定以影响快速模糊效果,然后再设定该距离范围以影响缩放参数。

在第一个合成中,我们分别对四个图层应用了快速模糊效果并为它们的模糊程度属性加入了相似的表达式,同时使用一个名为"Drag Me"的黄色固态层来控制受控图层的模糊程度。在表达式中我们使用了liner()插值算法将位移的范围从0至80缩减到40至0,所以当控制图层接近受控图层时,模糊效果将会变得更加强烈。

完成上面的设置后,我们就可以通过调整控制图层的位置来依次交互的影响四个受控图层,在渲染前,将控制图层的显示开关关掉,这样我们就可以完成整个动画了。

下面就是完整的表达式:

// 为受控图层加入快速模糊效果

// 为模糊程度加入表达式

// Point1 是当前受控图层的位置, point2 是控制图层的位置

point1=this_layer.position;

point2=this_https://www.doczj.com/doc/3c15415877.html,yer("Drag Me").position;

// 计算出两点之间的矢量线段

delta=sub(point1, point2);

// 计算出该矢量的长度

distance=length(delta);

//使用linear() 的方法将distance 的范围重新设定为40至0

linear(distance, 0, 80, 40, 0);

实例应用:缩放

在第二个合成中,我们将类似的表达式应用在了受控图层的缩放属性上,创建一个动态缩放的效果:

在这里表达式的书写基本上与前一个合成中的相同,因为缩放属性是一个二维数组(如果转化为3D图层就是三维数组),我们只需要将最后一句重新调整一下就可以了,(要详细了解矢量与数组单击这里)

//重新设定距离范围,以使图层越接近时缩放值越大,图层距离越远时,缩放值越小linear(distance, 0, 80, [250,250], [75,75]);

三角函数——sine(正弦),cosine(余弦)与(tangent)正切

三角函数是几何学的一个分支,用来研究三角形中边和角的关系。我们前面提到过,矢量可以由三角形组成,所以我们可以对矢量应用三角函数。

三角函数主要包括sine(正弦),cosine(余弦)与(tangent)正切,我们将角A作为需要计算的角度,函数关系如下图所示:

角A的正弦值等于该角的对边除以该角的斜边,角A的余弦值等于该角的邻边除以该角的斜边,角A的正切值等于该角的对边除以该角的临边,我们可以使用下面的助记符来快速记忆这些函数:

在Javascript语言中。三角函数包含在“math”对象中,所以我们这样书写三角函数:Math.sin(angle)

Math.cos(angle)

Math.tan(angle)

所有的三角函数的返回值均为数字(标量),正弦和余弦函数的返回值的范围为-1至1,正切函数的返回值范围为负整数至正整数。

弧度

在Javascript中,我们使用三角函数时用弧度来表示一个角而不是用度来表示一个角,弧度仅仅是一种不同于度的角度度量单位。

具体的说,弧度就是角度在圆周上所对应的一段弧线的长度,如下图所示:

因为圆的周长等于2*PI*radius,所以一个完整的圆周期(360度)就等于2PI弧度,因为PI 的近似值3.1414926535897932384626433832因此,我们可以利用公式1弧度=360/2*PI 得到1弧度近似等于57.30度;同样,1度=2*PI/360=0.017弧度。

在这里需要强调一下,AE中的角度以度而非弧度来计量,所以在使用相关的表达式进行计算时就需要进行单位之间的转换。我们可以使用上面提到过的交换率来换算单位,频繁的进行单位转换计算一定会泯灭我们的设计灵感,AE为我们提供了两个非常实用的转换函数,以提高我们的设计效率与水准:

radians_to_degrees(angle)

degrees_to_radians(angle)

例如,下面的表达式将计算当前图层旋转角度的正弦值:

Math.sin(degrees_to_radians(rotation));

该表达式首先将旋转参数单位从度转换到弧度,然后应用到三角函数中计算出该角的正弦值。计算未知边长度

在一个直角三角形中,如果我们知道了一条边的长度和一个角的度数,就可以利用三角函数计算出其他边的长度。(如果我们只知道两条边的长度可以使用勾股定理计算出另外一条边的长度)

前面的教程我们已经提到过,三角函数就是两条边的比值,所以我们可以使用公式来计算出任意一条边的长度:

opposite = hypotenuse*sin(A)

adjacent = hypotenuse*cos(A)

hypotenuse = opposite/sin(A) or adjacent/cos(A)

稍后,我们会将这种方法应用到实际的制作中,现在我们需要利用这些方程来研究一些关系特性。例如,通过第一个方程我们就可以总结出有两种方法来增加对边的长度:增加斜边的长度或者增加角A的正弦值;同样,可以通过增加斜边的长度和角A的余弦值来增大邻边的长度。

经验和勾股定理告诉我们,直角三角形中两条直角边互为消长关系,一条直角边的增加将导致另一条直角边的减小——除非斜边也增大。

因此,正弦函数与余弦函数也互为相反关系:

对边值越大,临边值越小

// 利用上面的公式计算出对边与临边

hypotenuse*sin(A) gets bigger, hypotenuse*cos(A) gets smaller.

// 我们可以忽略斜边值

sin(A) gets bigger, cos(A) gets smaller

从上面的方程式中我们可以看出,角的正弦值越大,其余弦值就越小,我们将在后面的教程

中讨论这种函数关系。

图象:sine(正弦)、cosine(余弦)与Tangent(正切)

在前面的教程中,我们已经明确了角度及边与三角函数之间的关系:

对于小于90度的角,增加角A的度数,也会增加该角对边的长度(假设斜边的长度保持不变),因此角A的正弦值也会随着增大,同时角A的临边将变短,同样角A的余弦值也会减小。

对于大于90度的角,可以理解为将相应角(180-大于90度的角)所在的三角形水平翻转,因此该角的对边与临边就会相应的减小或增大(斜边的长度不变):

这样看来,该角的正弦值就会减小,余弦值变大。当角度大于180度时,变化规律与大于90度小于180角的变化规律相同,当角度大于270度时,变化规律同小于90度角的变化规律。当大于360度时,整个变化规律又重复进行——三角函数是周期性变化的,最小正周期为360度:

如果我们使用图象来表示0至360度角的正弦曲线,如下图所示:

余弦值的图象与正弦图象类似,90度为一个相位。我们可以发现当一个角的正弦值为1或者是-1时,余弦值为0:

正切函数的图象与正弦余弦函数的图象截然不同,从下面的正切图象中,我们可以看到当角度为90度或者是270度时,正切值趋近于无限大,当接近这些角度时,该角的临边趋近于0,该角的对边趋近于该角的斜边。因为无限大不是一个合理的返回值,所以当AE计算到tan(90)或tan(270)时,其返回值为一个非常大的值:

相关主题
文本预览
相关文档 最新文档