虽然Flash拥有越来越强大的周边功能,但其核心依然是一款动画制作软件。在Flash设计环境中,不编写脚本代码,也能快速制作出效果惊人的时间轴动画。但此类动画是固定的,无法根据环境动态调整。使用ActionScript生成和控制动画,才能随心驾驭动画的细节,并完成仿真运动和用户交互等高级功能。
动画定时器
高级语言都会提供定时器,AS3更不例外。在脚本代码中,可以通过设置定时器控制动画帧率。
动画要素
动画是利用人眼视觉残留的特性来完成对真实世界运动的模拟。动画必须包含三个要素:对象、帧率、轨迹。
毫无疑问,任何动画都需要有对象。通过后期的编辑和组合,在一个场景里最终可以存在多个运动对象。但在动画设计阶段必须单独处理,每次只操作一个对象。
帧率(FrameRate)表示动画影片在单位时间内播放的动画帧数量。帧率越高,动画的表现就越平滑。但帧率也并不是越高越好,在Flash动画中,过高的时间轴帧率会耗费更多的系统资源。时快时慢的高帧率动画反而不如较低帧率的流畅动画。一般而言,动画达到24帧/秒的帧率就已经很流畅平滑了。对于一串动画序列,通过改变帧率,可以调节动作的快慢。
轨迹则是一个抽象概念,主要描述动画对象在单位时间内的属性变化情况。在以时间为x轴,属性为y轴的平面坐标系中,轨迹能被图像化的绘制出来。
轨迹不仅是描述对象空间运动的,也可以描述颜色、透明度、形状、大小等各种属性的变化。一个动画对象在时间线内alpha透明度的变化轨迹如图8-1所示。
根据动画的不同,轨迹的图像可以是线性的,也可以是非线性的;轨迹可以是连续平滑的,也可以是随机分布的。总而言之,轨迹就是描述运动对象属性变化情况的一个数据序列。
在创建Flash时间轴动画时,动画帧率与Flash项目的默认帧率相同。要加速动画对象的运动变化,只能通过改变轨迹实现。具体有两种办法:一种是增加单位时间内属性的变化量,一种是减少单位变化量需要的时间。形象而言,提高跑步速度可以有两种方式:或者在10秒内多跑几米,或者是减少跑100米所需的时间。无论选择何种方式,都可以达到相同的效果。
Timer类
定时器类(TimerClass)是ActionScript 3.0的内置类,通过AS3的事件分发响应机制实现周期触发。定时器是一个简单却又极为常用的类,系统全面的掌握它是非常必要的。
Timer类的属性如表8-1所示:
表8-1 Timer类的属性
名 称 | 类 型 | 说 明 |
currentCount | int | 统计定时器开始后累计触发次数。该属性为只读属性,用户不能改变 |
delay | Number | 以毫秒为单位的定时器延时周期。两次定时器触发时间之间的间隔。注意,一秒等于1000毫秒 |
repeatCount | int | 总触发次数,当累计触发次数达到总触发次数后,定时器就会停止 |
running | Boolean | 定时器的运行状态。定时器在运行则为true,定时器停止或未启动则为false。注意该属性为只读属性,不能通过设置该属性控制定时器状态。对定时器进行操作必须使用它内置的方法 |
使用Timer类的构造函数“Timer(delay:Number,repeatCount:int=0)”可以直接创建一个功能完备的定时器。此函数包含两个参数,分别是该类的delay属性和repeatCount属性。定时器创建后会保持停止,直到使用“start()”方法启动后,才会开始计时。
使用定时器
当定时器启动后,会每隔delay周期发出timer事件,必须在代码中设定对此事件的侦听,方可达到定时执行任务的目的。
var myTimer:Timer=new Timer(80,100);
myTimer.addEventListener("timer", timerhandler);//注意,事件timer必须全部小写
myTimer.start();
//事件处理函数
function timerhandler(event:TimerEvent):void{
//进行用户操作
}
以上代码创建了一个总触发次数为100次的定时器myTimer。当myTimer启动后,每隔80毫秒会发出一次定时器触发事件。用“addEventListener()”函数设定timer事件的监听,并编写timerhandler()来处理这个事件。一切就绪后,使用“start()”方法启动定时器。
在定时器启动后,使用currentCount属性查询当前累计触发次数,使用“stop()”方法可以停止一个定时器。需要指出的是:“stop()”方法不过是暂停了定时器,并没有清除定时器。当一个定时器被“stop()”方法停止后,Timer对象的currentCount并没有被清除。当再次使用“start()”方法启动Timer对象时,定时器将继续执行,直到触发次数达到repeatCount属性规定的数值。用户不能在代码中为CurrentCount赋值,要改变currentCount属性,只能使用“reset()”方法。“reset()”方法可以清零定时器的currentCount属性。
当一个定时器的触发次数达到设定值repeatCount时,FlashPlayer将发送timeComplete事件。通过响应此事件,可以重设Time定时器并令其继续运行下去。
用户可以同时设定多个定时器。多个定时器之间平行存在,互不影响。
精确性
Timer定时器是精确的,但是定时器的执行结果并非绝对精确。无论是Flash还是Flex,最终的应用程序都是以SWF文件存储。而FlashPlayer在解释SWF文件时,会建立基于帧率的周期循环。每次舞台更新的时间间隔是固定的,脚本中的舞台操作会受到时间轴帧率的制约。
作为一个多线程的应用程序,FlashPlayer执行脚本不需要依赖帧率,但是所有的屏幕输出都要借助FlashPlayer的渲染引擎。如果时间轴帧率为10,则运行时舞台每100毫秒播放一帧。当间隔为80毫秒的定时器触发时,SWF应用程序立刻执行该定时器的侦听函数,但是在定时器侦听函数中的任何屏幕操作,都不会及时的反应在舞台上。只有在100毫秒时,FlashPlayer才会更新舞台显示。定时器在160毫秒第二次触发时,SWF应用程序需在200毫秒更新舞台显示。理论上8000毫秒内执行100次定时器,但实际上在帧率为10的SWF应用中,舞台更新只有80次。有可能在舞台刷新间隔内,连续执行两次定时器操作。
定时器的触发事件间隔可以自由设置,所有的定时器事件都不会错过。屏幕显示虽然不是实时更新,但是由于刷新的速度很快,不会造成显著影响。实际上,任何语言的定时器都要受制于系统时钟,都不是绝对精确的。