术语Tween翻译为补间,这个术语来自于传统的动画技术,动画分为关键帧和中间帧。一些制作者绘制关键帧,而另外一些人负责填充关键帧之间繁琐的中间帧。这种制作方法对Flash同样有效。在时间轴上,设计者可以定义关键帧,然后由Flash来完成填补关键帧之间内容的琐碎工作。将这段帧导出到SWF文件中,这个SWF文件就可以由Flash Player播放。一般将这样的操作称为时间轴补间。这种制作动画的方式,在动画运行的过程中不能修改其中的中间帧,由此也将它称为设计阶段的补间动画。与此相对的概念是动态的,也就是使用ActionScript编写的、可以在运行时修改的补间技术,这样就摆脱了时间轴的束缚,对于动画而言,时间轴补间是静态的、迟钝的。而使用ActionScript可以制作交互的、动态的运动,比时间轴补间更平滑、更生动。通常,这要涉及到一些数学公式和物理原理。下面就让我们探索使用ActionScript产生动态补间的各种方法。
一、运动的概念
从程序员的角度来看,运动是由什么构成?为了简化这个问题,最初只考虑一维的运动。对于使用ActionScript动态生成的运动而言,运动是位置随时间推移所发生的可度量的改变。运动设计3个关键因素:位置、时间和起始位置。
1、位置。在任意给定的时间,运动都有确定的数值,也就是当前的位置。当位置的值发生改变时,就发生了运动。
2、时间。运动是随着时间的推移而发生的。通常,时间是用正数来度量的。一般情况下,运动的时间从零开始,向正数跳动。
3、起始位置。运动必须从一个位置开始。从观察者的角度来看,运动是从开始观察它的那一刻开始的。也就是说,这一时刻是时间零点。于是将时间为零时时所处的位置称为起始位置。
值得注意的是,位置并不仅仅代表物理位置,它可以表示任何用数值表示的值。可以是一些影片剪辑的属性,如x、scaleY和alpha等。更具体地说,位置量应该是一个一维的实数,是一个标量而不是向量。这个数字可以是正数、负数或零,可以是整数或是小数。当然,更高维的空间中也存在着运动,比如二维和三维的运动。多维的位置通常可以划分为几个一维的位置。比如,Flash的舞台是一个二维的空间,由x和y坐标构成,而且这两者是相互独立的。而有的属性不是相互独立的,比如width、height和scaleX、scaleY属性,改变其中的一个另一个也会受到影响。
时间对于运动而言是至关重要的,位置是随着时间而变化的。任何事物都不能在零时间内运动,也不可能在同一时刻位于两个不同的位置。也就是说,位置需要根据时间变化而变化,而且在任意指定的时间点只能有一个值。
因为位置和时间之间存在着一对一的关系,所以说位置是时间的函数。这表示,一个指定时间有且只有一个相对应的位置。用数学公式来表述,即:
用p表示位置,t表示时间:
p = f(t)
给定时间,得到位置。因为ActionScript函数可以返回一个值,可以看到时间和位置之间一对一关系的重要性。
二、标准指数滑动
使用ActionScript编写运动最著名的就是标准指数滑动了。在Keith Peters的《Foundation ActionScript 3.0 Animation : Make things move》一书的第八章详细讨论的缓动其实就是标准指数滑动。实际上,标准指数滑动是个非常基础的概念,它表示物体向着目标前进,并逐渐减慢速度直至停止。标准指数滑动的算法是:1)由于速度与距离是成比例的,所以确定一个分数作为比例系数。这个系数越接近1,运动速度就会越快;系数越接近0,运动速度就会越慢。设置这个变量名为easing。2)确定目标的位置。只需要一个简单的 x,y 坐标就可以了。3)确定物体到达目标的距离。只需要从物体的x,y坐标中减去目标的x,y即可。4)根据这个距离以及easing系数计算物体运动的水平速度vx和垂直速度vy。5)更新物体的位置。可以通过下列代码中看出这种滑动技术:
private function onEnterFrame(event:Event):void{ var vx:Number = (targetX – this.x) * easing; var vy:Number = (targetY – this.y) * easing; this.x += vx; this.y += vy; }
一般将这种运动称为缓出。之所以称它为指数滑动,是因为运动的速度可以用一个指数表达式来表示,将在后面讲解该表达式。
其实,标准指数滑动的思想非常简单,例如,缓动系数为0.5,假设离目标点10米,那么第一次移动5米,第二次2.5米,然后1.25米,然后0.625米,等等。古希腊哲学家奇诺(Zeno)在他的一个著名悖论中提出了这个思想:物体要从 A 点到达 B 点,它首先要移动到两点间一半的距离。然后物体再从该点出发,到达与 B 点距离一半的距离。然后再折半。每次只移动离目标一半的距离,从理论上讲位置越来越接近目标,但是永远无法准确地到达目标点。奇诺的看法看起来是合理的,至少在量子理论表明空间并不是无限可分的之前是这样的。但是在Flash中,一次最少能移动的距离单位是twip,也就是1/20像素。在 Flash 内部计算单位都采用twip像素,包括所有Sprite、影片剪辑和其它舞台对象。因此,在显示影片位置时,这个数值永远是0.05的倍数。
一般来说,标准指数滑动是一个动态的缓出运动,实现的方法非常简单,这也正是它得到广泛应用的原因。但是,它并不完美,至少有下面这些问题。首先,这种技术只能用于缓出,不能用于缓入。同样,产生的运动效果与F1ash时间轴生成的缓动并不相同。与时间轴补间产生的缓出效果相比,这种滑动技术的速度起初太快,然后在接近终点时又变得太慢。 第二,不能根据指定的时间直接计算出运动的位置。例如,不能直接知道在10帧之后运动物体会位于哪个位置。每帧的位置都是根据前一帧的位置确定的。所以必须从头执行整个过程,才能得到各个时间的位置。没有简单的办法可以跳转到补间中的任意一帧。第三,不能直接指定运动的持续时间。标准指数滑动不能将运动指定为20帧长度。实际上,它根据距离来决定速度。通过调整系数来让运动过程变快或变慢,但是需要不断尝试才能使运动具有想要的长度。注意到这些缺点之后,所以需要找到标准指数滑动的替代方案。
补间可以定义为从一个位置向另一个位置过渡的中间帧。补间也可以看作是一种运动,它符合运动是位置随着时间改变的定义。既然补间是一种运动,所以它也具有运动的3个基本因素:位置、时间和起始位置。此外,补间还具有另外两个基本特征:持续时间和结束位置。
1、持续时间。补间必须会结束,它不能永远不到达目标。也就是说,补间的持续时间不能是无限的,同时还必须大约零。
2、结束位置。补间填补了两个关键帧之间的空白帧,能够使物体从A点移动到B点。那么点A就是起始位置,点B就是结束位置。所以,结束位置也是补间必须具备的基本要素。
补间函数的目的是根据补间的基本特征和指定的时间,计算出当前位置。补间的基本特征包括起始位置、结束位置和持续时间。需要向函数传递4个参数:时间、起始位置、结束位置和持续时间,函数返回值是位置。因此,补间函数应该大致具有如下结构:
function Tween(time, begin, final, duration){ return position }
另外,还可以用位置的改变来代替结束位置,在这种情况下,函数的结构是:
function Tween(time, begin, change, duration){ return position }
还可以将参数名称缩短为一个字母以提高速度,长变量名的查询时间比短变量名要长。这是由于解析器的内部散列过程造成的。所以函数还可以进一步优化为:
function Tween( t, b, c, d ){ return position }