空間站

          北極心空

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks

          這段時間身體欠佳,經常頭暈。醫生說并無大礙,可我服了藥也不見有多少好轉。因此我很久沒有更新Blog了。

          針對大家關于Struts 2的問題,我正著手開發一個應用程序例子。這個例子以ASP.NET的“Personal Web Site Stater Kit”應用程序作為藍本,采用“Spring 2 + Hiberante 3 + Struct 2”架構(姑且稱之:-)),并且會以“prototype+DWR”為基礎實現AJAX。

          在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 + this .wSpan;
                 
          this .temp.h = this ._isOverstep('h') ? this .transformed.h : this .temp.h + this .hSpan;
             }
          ,
             
             
          /* ------------------------------------------------------------------------
              | 用途:
              |    覆蓋父類的空白實現,刷新元素外觀
              ------------------------------------------------------------------------
          */

             _draw:
          function (frame) {
                 
          var x = frame.x + 'px';
                 
          var y = frame.y + 'px';
                 
          var w = frame.w + 'px';
                 
          var h = frame.h + 'px';        
                 
                 Element.setStyle(
          this .element, { left: x, top: y, width: w, height: h } );
             }

             
          }
          );
          清單2 ShapeAnimation.js

          ShapeAnimation類繼承Animation類,并覆蓋了其中的某些方法。最后,讓我們創建HTML文件,測試一下這個ShapeAnimation是否可以正確工作。代碼如下:

          <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
          < html xmlns ="http://www.w3.org/1999/xhtml" >
          < head >
             
          < title > ShapeAnimation Test </ title >

             
          < script type ="text/javascript" src ="prototype-1.4.0.js" ></ script >
             
          < script type ="text/javascript" src ="Animation.js" ></ script >
             
          < script type ="text/javascript" src ="ShapeAnimation.js" ></ script >

             
          < script type ="text/javascript" >  
                 
          var animation;  
                  
                  Event.observe(window, 'load', init,
          false );
                  
                 
          function init() {
                     
          var clip = $('clip');
                     
          var pos = Position.cumulativeOffset(clip);            
                      
                      animation
          = new ShapeAnimation(clip, 12 );
                      animation.createTweens( { x: pos[
          0 ], y: pos[ 1 ], w: 100 , h: 75 },
                                              { x:
          100 , y: 100 , w: 200 , h: 200 },
                                             
          24 );
                  }
                  
                 
          function play() {            
                      animation.play();            
                  }
                  
                 
          function stop() {
                      animation.stop();     
                  }
                  
                 
          function pause() {
                      animation.pause();    
                  }
             
          </ script >
          </ head >
          < body >
             
          < input type ="button" onclick ="play()" value ="Play" />
             
          < input type ="button" onclick ="stop()" value ="Stop" />
             
          < input type ="button" onclick ="pause()" value ="Pause" />< br />
             
          < br />
             
          < img src ="thumb.jpg" alt ="Thumb" id ="clip" style ="left: 13px; position: absolute; top: 52px;" />
          </ body >
          </ html >
          清單3 ShapeAnimationTest.htm

          分別在IE或Firefox中打開ShapeAnimationTest.htm,播擊“Play”、“Stop”和“Pause”按鈕工作正常。

          舉一反三

          上述例子,我創建了形狀動畫類。有了Animation類作為基類,當然我可以容易地創建更多的動畫類。下面我再舉一個裁剪動畫示例。代碼如下:

          var ClipAnimation = Class.create();
          ClipAnimation.prototype
          = Object.extend( new Animation(), {
            
             _createTweens:
          function (original, transformed, frames) {
                 
          this .tSpan = Math.round((transformed.t - original.t) / frames);
                 
          this .rSpan = Math.round((transformed.r - original.r) / frames);
                 
          this .bSpan = Math.round((transformed.b - original.b) / frames);
                 
          this .lSpan = Math.round((transformed.l - original.l) / frames);
             }
          ,
             
             _prepare:
          function ()
                 
          this .temp.t = this ._isOverstep('t') ? this .transformed.t : this .temp.t + this .tSpan;
                 
          this .temp.r = this ._isOverstep('r') ? this .transformed.r : this .temp.r + this .rSpan;
                 
          this .temp.b = this ._isOverstep('b') ? this .transformed.b : this .temp.b + this .bSpan;
                 
          this .temp.l = this ._isOverstep('l') ? this .transformed.l : this .temp.l + this .lSpan;
             }
          ,
             
             _draw:
          function (frame) {
                 
          var clipStyle = 'rect(' + frame.t + 'px ';
                 clipStyle
          = clipStyle + frame.r + 'px ';
                 clipStyle
          = clipStyle + frame.b + 'px ';
                 clipStyle
          = clipStyle + frame.l + 'px)';    
                 
                 Element.setStyle(
          this .element, { clip: clipStyle } );
             }

             
          }
          );
          清單4 ClipAnimation.js

          測試文件代碼如下:

          <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
          < html xmlns ="http://www.w3.org/1999/xhtml" >
          < head >
             
          < title > Untitled Page </ title >

             
          < script type ="text/javascript" src ="prototype-1.4.0.js" ></ script >
             
          < script type ="text/javascript" src ="Animation.js" ></ script >
             
          < script type ="text/javascript" src ="ClipAnimation.js" ></ script >

             
          < script type ="text/javascript" >  
                 
          var animation;  
                  
                  Event.observe(window, 'load', init,
          false );
                  
                 
          function init() {
                     
          var clip = $('clip');
                     
          var pos = Position.cumulativeOffset(clip);
                     
          var dimensions = Element.getDimensions(clip);
                      
                      animation
          = new ClipAnimation(clip, 12 );
                      animation.createTweens( { t:
          0 , r: dimensions.width, b: Element.getHeight(clip), l: 0 },
                                              { t:
          0 , r: dimensions.width, b: 0 , l: 0 },
                                             
          24 );
                  }
                  
                 
          function play() {            
                      animation.play();
                  }
                  
                 
          function stop() {
                      animation.stop();     
                  }
                  
                 
          function pause() {
                      animation.pause();    
                  }
             
          </ script >
          </ head >
          < body >
             
          < input type ="button" onclick ="play()" value ="Play" />
             
          < input type ="button" onclick ="stop()" value ="Stop" />
             
          < input type ="button" onclick ="pause()" value ="Pause" />< br />
             
          < br />
             
          < img src ="thumb.jpg" alt ="Thumb" id ="clip" style ="left: 13px; position: absolute; top: 52px;" />
          </ body >
          </ html >
          清單5 ClipAnimationTest.htm

          總結

          Prototype實現了部分的面向對象,對常用的操作提供了方便的封裝。這樣我們可以編寫具有更高可重性的Javascript代碼,將實現重HTML文件中分離出來,使程序結構更清晰可讀。

          點擊以下鏈接下載示例代碼

          posted on 2007-01-26 15:06 Max 閱讀(970) 評論(2)  編輯 收藏 引用 所屬分類: 方法與技巧(Tips & tricks)
          posted on 2007-04-19 13:45 蘆葦 閱讀(365) 評論(0)  編輯  收藏 所屬分類: JAVA其他
          主站蜘蛛池模板: 黄大仙区| 肥西县| 南江县| 监利县| 兰考县| 赤峰市| 工布江达县| 乐亭县| 保亭| 贡嘎县| 淳化县| 紫阳县| 海晏县| 南靖县| 乐昌市| 项城市| 万载县| 新疆| 罗平县| 通辽市| 镇巴县| 当雄县| 成都市| 卢氏县| 南昌市| 咸阳市| 大兴区| 东平县| 平远县| 祁连县| 祁东县| 辽源市| 平邑县| 衡水市| 岱山县| 田林县| 绵竹市| 克拉玛依市| 吉隆县| 双桥区| 东乡族自治县|