老赵点滴


  先做人,再做技术人员,最后做程序员。
  我的理想:“让外国人看中国人写的技术书籍和文章”。Try as I might
posts - 290, comments - 10850, trackbacks - 158, articles - 6
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

  Animation是AjaxControlToolkit中提供的经典模型之一,这个模型下的各种组件经过组合可以出现非常丰富的动画效果。Animation模型也是Microsoft AJAX Library客户端Component模型的经典案例,掌握了Animation几乎也相当于掌握了Component模型——甚至包括了Component模型的派生:Behavior模型和Control模型。在我看来,除了在“概念”上的区别之外,从技术角度分析它们几乎都是同样的东西。

  另外,Animation源代码中的注释甚至超过了代码本身的数量,因此它也是非常优秀的学习资料。

  Animation模型的基础是客户端AjaxControlToolkit.Animation.Animation类。为了编程方便,AjaxControlToolkit为AjaxControlToolkit.Animation命名空间取了一个别名“$AA”,因此我们在使用Animation类时可以通过“$AA.Animation”来访问它。

  下图为Animation的UML表示:

Animation类

  Animation类继承了Sys.Component类,因此它也含有Sys.Component的所有成员和特性,例如raisePropertyChanged方法和propertyChanged事件。它的主要成员如下:

构造函数:

  • Animation(target, duration, fps):用于构造一个Animation对象,初始化一些值,不多说了。

属性:

  • target:RW属性,DOM元素类型。表示Animation作用的DOM元素,例如ColorAnimation中改变颜色的那个对象。
  • duration:RW属性,Number类型,默认值为1。表示这个Animation从头至尾“播放”一遍所需的时间,单位为“秒”。
  • fps:RW属性,Number类型,必须是整数,默认值为25。fps即为frame per second,每秒多少帧。表示一秒钟的动画需要使用多少次变化进行。
  • animationTarget:只写属性(Bad Practice),String类型。通过ID查找target。
  • isActive:只读属性,Boolean类型。查看Animation是否处于活动状态(Play或Pause状态)。
  • isPlaying:只读属性,Boolean类型。查看Animation是否处于播放状态。
  • percentComplete:只读属性,Number类型。查看Animation已经播放的百分比。

方法:

  • dispose:销毁Animation对象,不多说了。
  • getAnimationValue:抽象方法。传入percentage作为参数,返回任意对象表示当前Animation状态。
  • setValue:抽象方法。传入一个表示Animation状态的对象用于更新Animation效果。
  • interpolate:传入start,end和percentage,返回start和end之间处于percentage位置的那个值。
  • onEnd:Animation终止时会调用的方法。
  • onStart:Animation启动时会调用的方法。
  • onStep:Animation运行时每一步会调用得方法,接受当前percentage作为参数。
  • pause:暂停Animation。
  • play:开始Animation。
  • stop:停止Animation。当finish参数为true,或者没有提供finish参数时,Animation将会停留在最终状态。
  • raiseEnded:触发ended事件。
  • raiseStarted:触发started事件。
  • setOwner:设置Animation的Owner

事件:

  • ended:Animation结束时触发的事件。
  • started:Animation开始时触发的事件。

域变量(是这样翻译吗?):

  • DynamicProperties:Object类型。其实是一个字典,存放了Animation在开始前需要进行的操作。

 

  上面的成员描述简单到了似乎没有多大价值的地步,因此我会再针对一些成员进行解释。不过一些涉及到高级话题(比如Animation的父子关系,从XML中解析Animation等等)的成员,暂时就不在这片文章中进行讲解了。另外,这片文章也会跳过简单成员的一些涉及到高级话题的细节。

  当我们调用Animaion对象的play方法时,它会初始化一个Timer对象,并调用onStart方法。在每次Timer的tick事件触发时,Animation则会得到当前的percentage,作为参数执行onStep方法。当我们当调用pause方法时,它只是简单地停止Timer对象。而我们当我们调用stop方法时,则Timer对象会被销毁,并调用onEnd方法。onStart、onStep和onEnd的方法的原始实现都非常简单,例如onStart和onEnd分别调用了raiseStarted和raiseEnded方法,用于触发started事件和ended事件。

  Timer的interval又是如何决定的呢?Animation在播放时,通过Fps就可以确定Animation中相邻两个step的间隔长度,这就是Timer的interval。从理论上讲,fps × step = 1000(毫秒),但是事实上,受到window.setInterval方法的限制,fps越高则误差越大。显然,Fps配合duration就能够算出每个step过后的percentage。

  onStep的默认实现会自动将当前的percentage作为参数传入getAnimationValue方法,用于获得一个表示Animation状态的对象,然后再立即传入setValue方法用于更新Animation的样式。这个状态对象可以是一个简单的数字,也可以是一个表示许多信息的复杂对象。

  因此,如果实现的是一个简单的Animation时,一般只需要正确实现getAnimationValue和setValue两个抽象方法即可。在开发高级的Animiation时,可能我们也会覆盖onStart,onStep和onEnd方法。至于其他的方法,我们一般都直接使用Animation类中定义的实现,仅仅会在非常特殊的情况下才进行覆盖。

  在这里我准备了一个简单的CounterAnimtion类,用于在target元素中显示数字,以下则是它的实现:

CounterAnimation
Type.registerNamespace("Jeffz");

Jeffz.CounterAnimation = function(target, duration, fps)
{
    Jeffz.CounterAnimation.initializeBase(this, arguments);
    
    this._startValue = 0;
    this._endValue = 100;
}
Jeffz.CounterAnimation.prototype = 
{
    get_startValue : function()
    {
        return this._startValue;
    },
    set_startValue : function(value)
    {
        if (this._startValue !== value)
        {
            this._startValue = value;
            this.raisePropertyChanged("startValue");
        }
    },
    
    get_endValue : function()
    {
        return this._endValue;
    },
    set_endValue : function(value)
    {
        if (this._endValue !== value)
        {
            this._endValue = value;
            this.raisePropertyChanged("endValue");
        }
    },
    
    getAnimatedValue : function(percentage)
    {
        return this.interpolate(this._startValue, this._endValue, percentage);
    },
    
    setValue : function(value)
    {
        this.get_target().innerHTML = Math.round(value);
    }
}
Jeffz.CounterAnimation.registerClass("Jeffz.CounterAnimation", $AA.Animation);

 

  CounterAnimation定义了两个额外的属性,startValue和endValue,表示初始值和末尾值。然后我们又实现了getAnimationValue和setValue方法。所有的实现都非常简单。在这里,我们用到了定义在Animation类中的一个辅助方法interpolate。这个方法接受start,end和percentage三个参数,返回start,end两个值之间处于percentage位置处的值。例如:interpolate(100, 300, 50)则返回200。

  这个Animation的使用效果如下:

Duration:
Fps:
Start Value:
End Value:

 

  需要注意的是,这里用的Timer并不是MicrosoftAjaxTimer.js中的Sys._Timer类,而是重新定义的Sys.Timer类。Sys._Timer类是为UpdatePanel服务的,它依赖于PageRequestManager等对象。Sys.Timer是AjaxControlToolkit中定义的组件,封装了window.setInterval方法,是个非常通用的Timer组件。如果需要的话,您也可以单独将它取出并使用。

Feedback

#1楼    回复  引用  查看    

2007-03-14 14:20 by 老夫子系      
好文章!

#2楼 [楼主]   回复  引用  查看    

2007-03-14 14:23 by Jeffrey Zhao      
@老夫子系
谢谢:)

#3楼 [楼主]   回复  引用  查看    

2007-03-14 14:24 by Jeffrey Zhao      
不得不承认FireFox2在JS运行效率等方面比IE7强不少,从Animation这种需要大量执行,大量绘制页面的操作上可以看出比较明显的差距。

#4楼    回复  引用  查看    

2007-03-14 15:11 by Ariel Y.      
吓一跳,误看成了Automation...

#5楼    回复  引用    

2007-03-14 15:25 by test [未注册用户]
就那么回事情,3天可以掌握的玩意

#6楼 [楼主]   回复  引用  查看    

2007-03-14 15:49 by Jeffrey Zhao      
@test
其实我也希望大家都像您这样牛,这样我们就不用老是跟着外国人了,这样就轮到我们写书外国人看翻译的,呵呵。:)

#7楼    回复  引用    

2007-03-14 16:48 by heweitykc [未注册用户]
老赵 牛!

#8楼    回复  引用  查看    

2007-03-14 17:05 by JesseZhao      
说写就写,还真是速度啊

#9楼 [楼主]   回复  引用  查看    

2007-03-14 17:08 by Jeffrey Zhao      
@JesseZhao
断断续续几天了,只是Post的间隔短,呵呵。

#10楼    回复  引用    

2007-03-14 17:43 by 怪怪 [未注册用户]
@test
你有病吧...。

就算3天能掌握,一年才掌握122个,况且现在大家用于学习而不是用于直接完成事情的时间都有限。如果有了老赵这样的人,对好多人来说3天变成了1天,另外两天就可以完成更多的事情,如果热心的宣讲者多一些,大家就都能进步的再快一些。

你要是嫉妒别人红,你就写点不是3天就弄明白的,何苦冷嘲热讽的。

#11楼    回复  引用  查看    

2007-03-14 23:50 by 在北京的湖南人      
老赵,问一下你,能不能在Accordion每一项里面都再嵌套一个Accordion啊?
我想用Accordion做产品的二级导航,不知道能不能实现?

#12楼 [楼主]   回复  引用  查看    

2007-03-15 00:04 by Jeffrey Zhao      
@在北京的湖南人
我想应该可以吧,不如您试试看?

#13楼    回复  引用    

2007-03-16 01:41 by jewelry [未注册用户]
我的browser game里面,
有一个js的2.5d的寻路算法
在ff上面比ie上面快3倍以上……
opera也速度很快

无论ie6还是ie7都慢啊……

#14楼 [楼主]   回复  引用  查看    

2007-03-16 02:05 by Jeffrey Zhao      
@jewelry
哇,jewelry大哥你也来啦。不知道为什么会这么慢,汗。

#15楼    回复  引用    

2007-05-18 09:31 by linlin [未注册用户]
我的animation类中没有你在
上面说的这些方法和属性,
只有
Children;
Equals;
GetHashCode;
Name;
Properties;
ToString;
Equals
这几个方法和属性是为什么?

#16楼 [楼主]   回复  引用  查看    

2007-05-18 12:54 by Jeffrey Zhao      
@linlin
我这篇文章说的是客户端的Animation类。

#17楼    回复  引用    

2007-09-06 15:43 by 小瞧老外 [未注册用户]
有本事,你用汉语写程序,你就真的牛了

#18楼 [楼主]   回复  引用  查看    

2007-09-06 22:56 by Jeffrey Zhao      
@小瞧老外
只要一个语言的输入速度不如英文,那么肯定不可能出现对应的主流编程语言,呵呵……

#19楼    回复  引用    

2007-10-04 14:16 by 哎11111 [未注册用户]
一大篇都不知你说了什么......

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-03-16 09:51 编辑过


相关链接: