谈谈scriptaculous动画效果库effect.js(原理和使用)

scriptaculous 包含以下几个部分:
builder.js :提供了一种方便的建立html元素的方法
controls.js :包含自动提示和动态编辑两个控件
dragdrop.js : 提供元素拖放的功能
effects.js   : 设计优良的 ajax效果库,这篇文章要讲的就是这个
slider.js   : 一个滑动条控件
关于每个部分的使用方法建议查看scriptaculous 的 官方文档,这篇文章只讲scriptaculous中的effect.js(动画效果库)这一部分
effects.js中提供了两种类型的动画效果,一种称为核心效果(core effect),一种称为组合效果(combination effect)
顾名思义,core effect提供了一种比较单一的效果,例如元素的渐变隐藏、元素的移动等等,所有的core effect都是继承于effect.base 这个基类,effect.base类实现了浏览器中用js表现一段动画效果的整个逻辑,而每个具体的core effect类实现该效果的表现代码就可以了
而combination effect把各种不同的core effect组合起来实现了一些比较复杂的动画效果
调用方法:
在header中引用scriptaculous文件:
<script src="lib/prototype.js" type="text/javascript"></script><script src="lib/scriptaculous.js" type="text/javascript"></script>

scriptaculous是建立在prototype之上的,所以要先引用prototype,如果你只想使用scriptaculous中的effect效果库,可以把第二句修改为<script src="lib/scriptaculous.js?load=effects" type="text/javascript"></script> 这样的话就不会把所有的scriptaculous文件都引入到页面了
第二步:实例化你想要的效果类:
例如: new effect.opacity("testdiv1",{from:1,to:0}) ,实现元素慢慢隐藏的效果,其中effect.opacity 是要实现的效果的名称,也是实现这个效果的类的名称,调用的时候要提供两个参数,其中第一个参数"testdiv1"指定该效果要作用的对象(html元素),可以是元素id或者是元素的引用,其中第二个参数 {from:1,to:0} 指定这个效果的具体参数,它是一个javascript对象,{from:1,to:0}在这里是表示不透明度由1变成0,也就是把元素慢慢变成透明了,持续时间是1秒钟(默认)
其他的效果调用方式跟effect.opacity基本一样,提供一个html元素以及一个js对象来指定效果的具体参数
比如 new effect.move("testdiv1",{x:20,y:30}) ,将id为testdiv1的元素慢慢的向下移动20px,同时向右移动30px
其中第二个参数默认是:
{
   duration:    1.0,    // 持续时间
   fps:         60.0,   // 每秒的帧数
   sync:        false, // 只有在同时播放一些动画效果的时候才需要设置为true,下面会介绍
   from:        0.0,    // 从哪里开始
   to:          1.0,     // 到那里结束    //这两个参数下一节会说明
   delay:       0.0   // 延迟执行的秒数,可以看成是开始执行的时间
}
除了指定这些参数外,还可以在这个参数中指定动画的事件处理函数,例如afterfinish等
{
    from:1,
    to:0,
    afterfinish:function(){alert("运行结束了")}
}
初步认识effect.base和core effects
effect.base是所有core effects效果类的基类,也是创建我们自己的效果类的基础
effect.base类使用了flash中时间线(timeline)的概念实现了浏览器中的动画逻辑,实例化一个效果(effect对象)相当于建立了一条时间线,effect.base使用我们提供的参数(比如开始时间, 结束时间,每秒的帧数)来初始化这个时间线, 然后在我们指定的时间内运行(相当于flash中的播放),在具体的某个effect类中只要实现每帧的显示代码(update方法)以及初始化的一些操作就可以了
比如上面例子的effect.opacity效果,下面是整个的实现代码:
effect.opacity = class.create();
object.extend(object.extend(effect.opacity.prototype, effect.base.prototype), {
   initialize: function(element) {
     this.element = $(element);
     if(!this.element) throw(effect._elementdoesnotexisterror);
     // make this work on ie on elements without ‘layout’
     if(/msie/.test(navigator.useragent) && !window.opera && (!this.element.currentstyle.haslayout))
       this.element.setstyle({zoom: 1});
       var options = object.extend({
       from: this.element.getopacity() || 0.0,
       to:    1.0
     }, arguments[1] || {});
     this.start(options);
   },
   update: function(position) {
     this.element.setopacity(position);
   }
});
在这里我们只定义了构造函数initialize和实现设置元素透明度的update函数,这样一个效果类就建成了,而具体的动画实现逻辑全部在effect.base中实现了,effect.base在显示每帧的时候会自动调用上面的update方法
在initialize中执行一些初始化的必要操作,比如在上面的代码中判断要作用的目标元素是否存在,以及把动画的开始透明度设置为元素当前的透明度,注意需要在这个函数的最后调用this.start(options)来运行这个动画
update方法在每帧显示的时候被effect.base中的方法自动调用,传递给update的参数pisition指定当前帧的位置,注意跟当前帧不是一个概念(当前帧可以使用effect的属性currentframe获得),它表示的是当前帧映射到参数from和to的值,还是举个例子说明的好:
例如一个动画持续2秒钟,每秒的帧数是65,那么这个动画共有65*2=130帧,当播放了0.8秒时,那么当前帧就是65*0.8=52,默认情况下(from=0, to=1)那么传递给update的参数pisition就是 52/130或者说是pos=0.8/2=0.4=40%,可以看着是执行了整个动画的百分之几了,如果你实例化effect的时候提供了{from: 1 , to:0.1}, 在effect.opacity中表示透明度有1渐变到0.1,这个时候传递给update的参数position就等于0.4*(0.1-1)+1=0.64(from+(to-from)*pos),正好是在渐变过程中我们要设置的opacity值,所以在update中只用this.element.setopacity(position)一句代码就行了
core effects中的属性、方法以及事件

除了上面说的currentframe属性,在effect.base中还提供了另外一个属性:state,它表示当前动画的运行状态,它有三种不同的值:
"idle": effect实例已经建立,但是还没有开始运行
"running": 动画正在运行中
"finished": 动画已经运行结束
另外两个属性是:starton和finishon,他们的单位是毫秒ms,不过这些属性一般都很少使用
在effect.base中定义了很多的事件:beforestart,beforesetup,aftersetup,beforeupdate,afterupdate,beforefinish,afterfinish
上面是按照这些事件的触发顺序排列的,这些事件的处理函数在用户建立相应的effect实例的时候传递进来,上上节的调用方法一节有说明
只要你高兴你可以使用更长的事件名称,如afterfinishinternal,它跟afterfinish是等价的
继承自effect.base的effect类中,除了两个必须要实现的initialize和update方法外,还可以实现另外两个方法:setup()和finish(),setup在运行动画的第一帧前被调用,finish在动画最后一帧运行后调用,可以在finish方法里定义一些还原和释放资源的操作
更多更有趣的除了简单的core effect外,scriptaculous中还包含更多的组合效果类,这里只简单的说一下实现的方法,而不是准备列一个清单以及具体的使用说明出来,我鼓励你直接深入到scriptaculous的源代码中去
1,怎么把两个动画链接起来:

使用afterfinishinternal,例如你想让一个元素左右摇动几下:
effect.shake = function(element) {
   element = $(element);
   var oldstyle = {
     top: element.getstyle(’top’),
     left: element.getstyle(’left’) };
     return new effect.move(element, 
       { x:   20, y: 0, duration: 0.05, afterfinishinternal: function(effect) {
     new effect.move(effect.element,
       { x: -40, y: 0, duration: 0.1,   afterfinishinternal: function(effect) {
     new effect.move(effect.element,
       { x:   40, y: 0, duration: 0.1,   afterfinishinternal: function(effect) {
     new effect.move(effect.element,
       { x: -40, y: 0, duration: 0.1,   afterfinishinternal: function(effect) {
     new effect.move(effect.element,
       { x:   40, y: 0, duration: 0.1,   afterfinishinternal: function(effect) {
     new effect.move(effect.element,
       { x: -20, y: 0, duration: 0.05, afterfinishinternal: function(effect) {
         effect.element.undopositioned().setstyle(oldstyle);
   }}) }}) }}) }}) }}) }});
}
2,怎么使两个效果平行的同时运行
使用effect.parallel,effect.parallel是一个core effect类,它的update方法调用每个你要执行的effct效果,使用起来也很简单:
effect.parallel(effects,options)其中effects是一个你希望同时运行的effect数组,例如:
new effect.parallel([
       new effect.opacity("testdiv1",{from:1,to:0,sync:true}) ,
       new effect.move("testdiv1",{x:20,y:30,sync:true}) 
    ],
   {duration:2,delay:1})
每个要执行的effect要把sync参数设置为true,否者它就自动运行了,这些effect将同时运行同时结束(由options参数中的duration和delay控制),所以你在这些effect中不需要设置这些参数了
3,根据css来实现动画效果
new effect.morph("testdiv1",{style:"class2"}):就可以实现把testdiv1的classname设置为class2,注意这个过程是一个动画效果,哈哈,自己试一试吧
其中effect.morph是一个core effect类,你可以像其他effect一样提供帧数,时间等参数
4,忘记说了的
effect.scopedqueue:任何sync参数为false的effect都是通过它来运行的,通过它可以把几个效果按照一定的时间顺序组合起来,一般在实现简单效果的时候很少使用
参考(你需要提前知道的):
scriptaculous是建立在prototype库之上的,所以要理解scriptaculous你首先应该对prototype有所了解,关于prototype你可以参考我写的prototype教程 

你可能感兴趣的:(谈谈scriptaculous动画效果库effect.js(原理和使用))