首頁  >  文章  >  web前端  >  實作JavaScript動畫的詳細介紹

實作JavaScript動畫的詳細介紹

黄舟
黄舟原創
2017-03-14 15:01:481299瀏覽

前言

現今,許多頁面上都有一些動畫效果。適當的動畫效果可以在一定程度上提高頁面的美觀度,具有提示效果的動畫可以增強頁面的易用性。

實現頁面動畫的途徑有兩種。一種是透過操作JavaScript間接操作CSS樣式,每隔一段時間更新一次;一種是直接透過CSS定義動畫。第二種方法在CSS3成熟之後被廣泛採用。在本文中,我們討論第一種方法的原理和實作。

JavaScript動畫實作原則

首先我們需要知道兩個重要的概念,動畫時間進程和動畫效果程式。

動畫時間進程指從時間上看動畫的完成度,是一個[0, 1]之間的數字。假設動畫於時間戳t1開始,要在t2結束,目前時間戳記為t,那麼該動畫目前的時間進程為(t-t1)/(t2-t1)。如果你不能理解,我建議你用紙筆畫出來。理解這一概念對理解本文至關重要。

動畫效果程序指被動畫的屬性目前的增量。假設我們要將#el元素的CSS <a href="http://www.php.cn/wiki/907.html" target="_blank">left</a># 屬性從100px變成200px,目前已經改變到了130px,那麼動畫目前的效果過程為130px - 100px = 30px

假設動畫時間進程和動畫效果進程都是線性的。那如果知道了動畫時間進程,一定可以得到動畫效果進程。

根據這個解釋,我們很快就可以寫出一個線性的動畫。

(function() {
      var begin, // 开始动画的时间
        el, start, end, duration; 
      var INTERVAL = 13;

      function now() {
        return (new Date).getTime();
      }

      /**
       * 执行一步动画(更新属性)
       */
      function _animLeft() {
        var pos = (now() - begin) / duration;
        if (pos >= 1.0) {
          return false;
        }
        return !!(el.style.left = start + (end - start) * pos);
      }

      /**
       * 对一个DOM执行动画,left从_start到_end,执行时间为
       * _duration毫秒。
       * 
       * @param  {object} _el       要执行动画的DOM节点
       * @param  {integer} _start   left的起始值
       * @param  {integer} _end     left的最终值
       * @param  {integer} _duration  动画执行时间
       */
      function animLeft(_el, _start, _end, _duration) {
        stopped = false;
        begin = now();
        el = _el;
        start = _start;
        end = _end;
        duration = _duration || 1000;

        var step = function() {
          if (_animLeft()) {
            setTimeout(step, INTERVAL);
          }
        };
        setTimeout(step, 0);
      }

      window.animLeft = animLeft;
    })();

    animLeft(
      document.getElementById(&#39;el&#39;),
      100,
      200
    )

JSBin

easing

很多時候,我們需要的動畫並非線性的。所謂非線性,從直覺來看,就是動畫速度會隨著時間而產生變化。那麼如何實現變速的動畫呢?

由前所述,我們知道透過控制動畫的時間進程就相當於控制動畫的效果進程。隨著真實世界的時間進程推移,動畫的時間進程跟著推移,從而控制動畫的效果進程推移。那麼,我們可以透過修改真實世界的時間進程和動畫的時間進程間的映射關係,從而控制動畫進程。如果你感到困惑,沒關係,請看下圖:

這是線性動畫中,真實世界的時間進程和動畫進程的映射關係。接下來,我們將其進行變換

這條曲線實際上是函數y = x * x的圖像。可以看到,兩個曲線的定義域和值域並沒有改變。曲線的斜率就是動畫的速率。接下來我們將兩張圖重疊在一起做個比較。

在真實世界的時間進行到x0的時候,動畫進程原本應該進行到y0,在進行變換之後,只進行到y1。到最後,百川歸海,兩條線交會於點(1, 1)。這裡,y = x * x變換函數(easing function)

我們修改一下上面的例子,讓動畫變成非線性的。

function ease(time) {
      return time * time;
    }

    /**
     * 执行一步动画(更新属性)
     */
    function _animLeft() {
      var pos = (now() - begin) / duration;
      if (pos >= 1.0) {
        return false;
      }
      pos = ease(pos);
      return !!(el.style.left = (start + (end - start) * pos) + "px");
    }

JSBin

我們可以在jQuery的程式碼中看到這樣的函數。

jQuery.easing = {
      linear: function( p ) {
        return p;
      },
      swing: function( p ) {
        return 0.5 - Math.cos( p * Math.PI ) / 2;
      }
    };

因此,你可以在jQuery.easing裡面加入easing function,使得jQuery支援新的動畫速率控制方法。注意,easing function的定義域和值域必須都為[0, 1]。

 jQuery.easing.myEasing = function( p ) { return ... }

總結

JavaScript動畫實質上也是透過操作CSS去執行動畫。動畫的時間進程可以決定動畫的效果流程。透過操作真實世界的時間進程和動畫的時間進程之間的關係,我們可以將線性動畫轉換成非線性的動畫。

#

以上是實作JavaScript動畫的詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn