2009-09-01 33 views
2

我想在我的網站中實現一個動畫:我可以在jQuery中實現每個動畫步驟的回調嗎?

  • 需要更新多個DOM元素。
  • 每個DOM元素都有它自己的動畫路徑(取決於它們的位置)
  • 並且仍然具有緩動效果。

如果我爲每個元素(隊列:false)調用jQuery的animate()函數,它會使每個元素與其餘元素略有不同步。有道理,因爲有多個定時器在運行。

我可以只有一個計時器事件,併爲每個動畫步驟回調? 喜歡的東西:

jQuery.fx.timeline(from, to, easing, function(step, total) { 

     var percentage = step/total; 
     // ...update DOM elements based on the percentage of the animation 

}); 

回答

4

JavaScript中的所有計時器均基於本地普通舊式JavaScript函數setInterval()setTimeout()。即使jQuery在內部使用它。

同步定時器的訣竅是確保只有一個調用setInterval(),所以自己構建一些東西。

的動畫可設計有:

  • 有10個步驟,每個具有30毫秒的間隔。
  • 總動畫需要300ms。
  • 在每個步驟中,當前的進步/百分比可以這樣計算:

    VAR百分比=(currentStep/totalSteps);現在

,每次你的函數被稱爲setInterval(),你可以一次設置所有的DOM元素到正確的位置。要找出一個元素應該是在每個動畫幀,可以使用:

var diff  = (to - from); 
var stepValue = from + diff * percentage; 

jQuery的緩動函數,可以直接調用,而最後陳述變成:

var stepValue = jQuery.easing[ easingMethod ](percentage, 0, from, diff); 

我「已經把這個變成一個類:

/** 
* Animation timeline, with a callback. 
*/ 
function AnimationTimeline(params, onstep) 
{ 
    // Copy values. 

    // Required: 
    this.from  = params.from || 0;   // e.g. 0% 
    this.to  = params.to || 1;   // e.g. 100% 
    this.onstep = onstep || params.onstep; // pass the callback. 

    // Optional 
    this.steps = params.steps || 10; 
    this.duration = params.duration || 300; 
    this.easing = params.easing || "linear"; 

    // Internal 
    this._diff = 0; 
    this._step = 1; 
    this._timer = 0; 
} 

jQuery.extend(AnimationTimeline.prototype, { 

    start: function() 
    { 
    if(this.from == this.to) 
     return; 

    if(this._timer > 0) 
    { 
     self.console && console.error("DOUBLE START!"); 
     return; 
    } 

    var myself = this;  
    this._diff = (this.to - this.from); 
    this._timer = setInterval(function() { myself.doStep() }, this.duration/this.steps); 
    } 

, stop: function() 
    { 
    clearInterval(this._timer); 
    this._timer = -1; 
    this._queue = []; 
    } 

, doStep: function() 
    { 
    // jQuery version of: stepValue = from + diff * percentage; 
    var percentage = (this._step/this.steps); 
    var stepValue = jQuery.easing[ this.easing ](percentage, 0, this.from, this._diff); 

    // Next step 
    var props = { animationId: this._timer + 10 
       , percentage: percentage 
       , from: this.from, to: this.to 
       , step: this._step, steps: this.steps 
       }; 
    if(++this._step > this.steps) 
    { 
     stepValue = this.to; // avoid rounding errors. 
     this.stop(); 
    } 

    // Callback 
    if(this.onstep(stepValue, props) === false) { 
     this.stop(); 
    } 
    } 
}); 

現在你可以使用:

var el1 = $("#element1"); 
var el2 = $("#element2"); 

var animation = new AnimationTimeline({ 
    easing: "swing" 
    , onstep: function(stepValue, animprops) 
    { 
     // This is called for every animation frame. Set the elements: 
     el1.css({ left: ..., top: ... }); 
     el2.css({ left: ..., top: ... }); 
    } 
    }); 

// And start it. 
animation.start(); 

添加暫停/恢復是讀者的練習。

1

你檢查jquery queue

你可以排列你的動畫併爲它們設置一個回調,我想如果你玩一點它,你可以達到你想要的。

希望它有幫助,思南。

2

一個簡單的答案。也許有人會像我一樣搜索它。

我們可以在動畫功能中使用「step」屬性。

$(obj).animate(
    { 
     left: 0 
    }, 
    { 
     duration: 50, 
     step: function(currentLeft){ 
      console.log("Left: ", currentLeft); 
     } 
    } 
); 

因此,對於每一個步驟,這將記錄當前的左邊位置

+0

啊,看來jQuery現在已經支持了。太好了! :) – vdboor 2013-04-05 16:34:20

相關問題