class rkuk implements ActionScript

我的ActionScript小路

« TweenLite源码剖析4一口气送上12本Flash CS4和ActionScript教程 »

TweenLite源码剖析5

该进入TweenLite自身的渲染过程了,也就是TweenLite.renderTime方法。这个方法是TweenLite tool中最复杂的操作之一,如果是第一次渲染还会在此过程中执行一些渲染前必要的初始化。再次强调一下这个方法中的time参数已经和父级时间线的时间相对独立开了,这里的time就是相对TweenLite起点状态经过的时间,并且这个时间并不像root时间线的绝对时间只会增大。这里的time当TweenLite正向运行的时候就在逐步增大,TweenLite如果反向运行那么这个time就在逐步减小,并且可能会减小到小于0。ok强调完毕那还是从代码开始: 

TweenLite.renderTime中的第一部分 [复制代码]
  1. var isComplete:Boolean, prevTime:Number = this.cachedTime;
  2. if(!this.active && !this.cachedPaused)
  3.     this.active = true;
  4. if (time >= this.cachedDuration) {
  5.     this.cachedTotalTime = this.cachedTime = this.cachedDuration;
  6.     this.ratio = 1;
  7.     isComplete = true;
  8.     if (this.cachedDuration == 0) {
  9.         if ((time == 0 || _rawPrevTime < 0) && _rawPrevTime != time) {
  10.             force = true;
  11.         }
  12.         _rawPrevTime = time;
  13.     }
  14. } else if (time <= 0) {
  15.     this.cachedTotalTime = this.cachedTime = this.ratio = 0;
  16.     if (time < 0) {
  17.         this.active = false;
  18.         if (this.cachedDuration == 0) {
  19.             if (_rawPrevTime > 0) {
  20.                 force = true;
  21.                 isComplete = true;
  22.             }
  23.             _rawPrevTime = time;
  24.         }
  25.     }
  26.     if (this.cachedReversed && prevTime != 0) {
  27.         isComplete = true;
  28.     }
  29. } else {
  30.     this.cachedTotalTime = this.cachedTime = time;
  31.     this.ratio = _ease(time, 0, 1, this.cachedDuration);
  32. }

这是TweenLite.renderTime中的第一部分代码,首先定义了两个变量,isComplete默认为false,在后面会检测当前TweenLite的Tween操作是否全部完成,如果完成就会将此标志设为true。prevTime表示的上一次渲染的时间,被初始化为cachedTime。因为每次渲染都会把当次渲染时间记录到cachedTime中,所以这里一开始prevTime获得的实际上就是上一次的渲染时间,这一次渲染时间的还要到后面才会被记录到cachedTime中。如果是第一次渲染,那么cachedTime等于0(在创建TweenLite时设定的)。

第二步就是设置TweenLite.active属性,前面说过这个属性表示TweenLite已经激活,那么下次渲染时TweenLite的父级时间线就不会再去判断TweenLite的启动时间已经到达,可以提高效率。但是有一种例外情况,虽然执行渲染但是不能把active激活,这种情况就是创建TweenLite时,如果设定TweenLite要immediateRender,但是有设置TweenLite要暂停,也就是创建时希望TweenLite把target设置为Tween的起始状态,但是不要让Tween运行,这个时候active就不能激活。

接下来if的三种情况分别是:当前渲染时间如果达到了整个Tween过程的总长度,当前渲染时间如果小于等于0(这种情况可能是TweenLite刚开始启动或者反向运行结束的时候),当前渲染时间介于TweenLite起始状态和终点状态之间。

第一种time >= this.cachedDuration的情况,表示正向运行时这一次渲染之后Tween过程就结束。这里面对Tween的过程持续时间为0的情况也作了处理。我想说明一下其中几个变量的意义,也就能明白这个处理过程了。time是当前TweenLite的渲染时间,之前已经详细说明过;cachedDuration是TweenLite整个过程的持续时间,在创建TweenLite的时候确定的;cachedTotalTime和cachedTime记录的是每次TweenLite渲染时间,在每次渲染中都会进行刷新,刷新之前表示上一次的渲染时间,刷新之后就表示这次渲染的时间,对于TweenLite来说,这两个属性的值永远相同,对于TweenMax来说则不一定相同,在谈到TweenMax时再作解释。ratio是一个比例参数,介于0和1之间,TweenLite tool对某个属性进行Tween的过程中,会按照这个比例来计算当前渲染时刻该属性的值是多少,计算公式为:当前属性值 = Tween起始状态的属性值+ ratio×(Tween终点状态的属性值- Tween起始状态的属性值),ease函数就是用来输出这个比例的,由此实现ease的不同效果。isComplete=true就表示整个Tween的过程已经执行完毕,renderTime函数后半部分会根据这个标志执行完成操作,例如发出完成事件等。还有就是force标志,force=true的时候表示即使当前渲染时间cachedTime(注意是刷新后的cachedTime)和上次渲染时间prevTime相同,也要强制进行这个渲染。_rawPrevTime仅在TweenLite过程持续时间为0时才使用,指示渲染的时候应该是渲染起始状态还是终点状态。当_rawPrevTime<0则当前应该渲染终点状态,每个TweenLite创建时_rawPrevTime会初始化为-1,反之如果_rawPrevTime>=0则当前应该渲染起始状态。

第二种time<=0的情况会在“当TweenLite的持续时间大于0,且正向运行的0时刻”或者“TweenLite反向运行结束”两种条件下发生。源码中执行的内容比较混乱,看了半天晕忽忽的,而且还发现个bug:当cachedDuration=0时,在正向渲染完成后,如果调用TweenLite.reverse想反向渲染,TweenLite就不能执行渲染,而且TweenLite还会无休止的反复进入renderTime做无效渲染。所以我把代码做了修改,修复了这个bug,看起来也简单些: 

修改TweenLite.renderTime中time<=0的情况 [复制代码]
  1. else if (time <= 0) {
  2.     this.cachedTotalTime = this.cachedTime = this.ratio = 0;
  3.     if (this.cachedDuration == 0) {
  4.         force = true;
  5.         isComplete = true;
  6.         _rawPrevTime = -1;//time;
  7.     }
  8.     else if (this.cachedReversed && prevTime != 0)
  9.         isComplete = true;
  10. }

第三种情况就是渲染TweenLite中间过程的情况,这个情况计算就比较简单,完成当前渲染时间的刷新和计算ease就可以了。

接下来有一个重要的过程要开始了,代码如下:

渲染前的初始化准备 [复制代码]
  1. if (this.cachedTime == prevTime && !force) {
  2.     return;
  3. }
  4. else if (!this.initted) {
  5.     init();
  6.     if (!isComplete && this.cachedTime) {
  7.         this.ratio = _ease(this.cachedTime, 0, 1, this.cachedDuration);
  8.     }
  9. }

首先判断上次渲染时间和这次渲染时间是否相同,如果相同的话,那么大部分情况都不必再重新渲染,因为相同时间的状态应该是一样的,但是仅有两种情况例外:一种就是设置了immediateRender时,这种情况往往都是被Tween的target的原本状态与Tween的起始状态不一致,需要立即渲染target到Tween的起始状态避免Tween启动时发生跳变,所以当设置了immediateRender时,TweenLite构造函数中调用renderTime就会赋予force=true;还有一种情况就是TweenLite持续时间为0时,这个时候虽然都是渲染0时刻的状态,但是却分为起始状态和终点状态,这也是前面特殊处理TweenLite.cachedDuration的原因。前面对这种情况的处理会在需要时把force设为true,以强制执行渲染。

接下来就是这个很重要的初始化过程,这个初始化过程只在第一次渲染时执行一次。注意这里强调是第一次渲染。所以如果设置了immediateRender,这个初始化就会在创建TweenLite时执行,如果没有设置immediateRender,那么这个初始化会在TweenLite启动时刻到来的第一次渲染中执行,执行完一次后下一次渲染中就不再执行这个初始化过程。这个初始化过程中的内容还不少,就放到下一篇中继续吧。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表

Copyright © 2008 www.rkuk.org, All Rights Reserved.

Powered By Z-Blog 1.8 Arwen Build 90619