编写基于Prototype的Javascript动画类

系统 1366 0

在AJAX如火如荼的今天,相信大家对Prototype这个Javascript类库应该都有所耳闻,它也的确使编写Javascript变得更简单。关于Prototype的文章,《Prototype简介》、《Prototype源码》诸如此类数不胜数;所以本文不会再做这几方面的介绍,并假设读者对Prototype有一定了解。

网页动画与原理

提到网页动画,大家首先想起应该Flash。不知道大家没有开发过Flash动画,故我想对此作一个简单的介绍(在我读大学的时候,对Flash也曾有过痴迷,所以也略懂一二)。Flash的动画主要分两类:渐变动画和逐帧动画。

  • 渐类动画——用户在时间轴上创建开始的关键帧和结束的关键帧,开发环境(Macromedia Profassional Flash 8等)会根据以上所创建的关键帧的颜色、位置和形状等,在计算出中间的过渡帧并添加到相应的时间轴上。这适用于创建简单的动画。
  • 逐帧动画——用户在时间轴的每帧上创建关键帧,并在其中绘制相应的图按。这适用于创建复杂的动画。

在Javascript中由于没有绘图API(应用程序接口),故只可以使用DOM+CSS改变元素的外观。而通过每隔一段时间调用一次改变元素外观的函数,实现类似Flash的渐类动画。

具体实现

因为不同的Javascript动画实现的基本原理都相同,所以可以创建一个基类将其抽象出来。代码如下:

var   Animation   =   Class.create();
Animation.prototype  
=   {
     
/* ------------------------------------------------------------------------
      | 用途:
      |    构造函数
      |
      | 参数:
      |    element 将要实现动画效果的元素
      |    fps     每秒播放帧数
      ------------------------------------------------------------------------
*/
     
     initialize:  
function (element, fps)   {
         
this .element   =   $(element);
         
this .interval   =   Math.round( 1000   /   fps);
         
         
this .isPlaying   =   false ;
         
this .currentFrame   =   1 ;   
         
         
// 创建一个用于存储中间状态的临时对象
          this .temp   =   { } ;             
     }
,
     
     
/* ------------------------------------------------------------------------
      | 用途:
      |    子类覆盖该方法,实现自定义的动画补间
      ------------------------------------------------------------------------
*/
     
     _createTweens:  
function (original, transformed, frames)   { } ,
     
     
/* ------------------------------------------------------------------------
      | 用途:
      |    创建动画补间
      |
      | 参数:
      |    original    开始状态
      |    transformed 结束状态
      |    frames      动画帧数
      ------------------------------------------------------------------------
*/
     
     createTweens:  
function (original, transformed, frames)   {
         
if ( this .isPlaying)   {
             
this .stop();
         }

         
         
this ._createTweens(original, transformed, frames);
             
         
this .original   =   original;
         
this .transformed   =   transformed;
         
this .frames   =   frames;
         
         
// 将开始状态拷贝到临时对象
         Object.extend( this .temp, original);        
     }
,
     
     
/* ------------------------------------------------------------------------
      | 用途:
      |    判断临时对象状态是否超出结束状态
      |
      | 参数:
      |    prop 状态属性名称
      ------------------------------------------------------------------------
*/
    
     _isOverstep:  
function (prop)   {
         
if ( this .original[prop]   <   this .transformed[prop])   {
             
return   this .temp[prop]   >   this .transformed[prop];  
         }
 
         
return   this .temp[prop]   <   this .transformed[prop];
     }

     
     _prepare:  
function ()   { } ,
     
     _draw:  
function (frame)   { } ,
     
     _drawFrame:  
function ()   {
         
if ( this .isPlaying)   {
             
if ( this .currentFrame   <   this .frames)   {                
                 
this ._prepare();
                 
this ._draw( this .temp);
                 
                 
this .currentFrame   ++ ;
             }
  else   {
                 
// 最后一帧绘制结束状态            
                  this ._draw( this .transformed);
                 
this .stop();
             }

         }

     }
,
     
     _play:  
function ()   { } ,
     
     play:  
function ()   {
         
if ( ! this .isPlaying)   {
             
this ._play();
             
             
this .isPlaying   =   true ;
             
this .timer   =   setInterval( this ._drawFrame.bind( this ),   this .interval);            
         }

     }
,
     
     _stop:  
function ()   { } ,
     
     stop:  
function ()   {
         
if ( this .isPlaying)   {
             
this ._stop();
             
             
// 回到开始状态
              this .isPlaying   =   false ;
             
this .currentFrame   =   1 ;
             
             Object.extend(
this .temp,   this .original);
             clearInterval(
this .timer);
         }

     }
,
     
     _pause:  
function ()   { } ,
     
     pause:  
function ()   {
         
if ( this .isPlaying)   {      
             
this ._pause();
                   
             
this .isPlaying   =   false ;
             clearInterval(
this .timer);
         }

     }

}
清单1 Animation.js

Animation类实现了一些公用的管理内部状态的操作,如播放动画、停止动画和暂停动画等。接下来,创建特定的动画变得相当容易了,下面让我们来看一个形状和位置渐变的动画实现,代码如下:

var   ShapeAnimation   =   Class.create();
ShapeAnimation.prototype  
=   Object.extend( new   Animation(),   {
    
     
/* ------------------------------------------------------------------------
      | 用途:
      |    覆盖父类的空白实现,计算每帧的变化量
      ------------------------------------------------------------------------
*/
     
     _createTweens:  
function (original, transformed, frames)   {
         
this .xSpan   =   Math.round((transformed.x   -   original.x)   /   frames);
         
this .ySpan   =   Math.round((transformed.y   -   original.y)   /   frames);
         
this .wSpan   =   Math.round((transformed.w   -   original.w)   /   frames);
         
this .hSpan   =   Math.round((transformed.h   -   original.h)   /   frames);
     }
,
     
     
/* ------------------------------------------------------------------------
      | 用途:
      |    覆盖父类的空白实现,计算当前的状态。如果超出结束状态,保持结束状态不变
      ------------------------------------------------------------------------
*/

     _prepare:  
function ()  
         
this .temp.x   =   this ._isOverstep('x')   ?   this .transformed.x :   this .temp.x   +   this .xSpan;
         
this .temp.y   =   this ._isOverstep('r')   ?   this .transformed.y :   this .temp.y   +   this .ySpan;
         
this .temp.w   =   this ._isOverstep('w')   ?   this .transformed.w :   this .temp.w   +
分享到:
评论

编写基于Prototype的Javascript动画类


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论