2011-10-06 64 views
0

我遇到了一些問題,我試圖對元素進行動畫處理。我有一個遞歸函數動畫,其中包含setTimeout來延遲動畫。問題是調用遞歸方法後的下一行在調用動畫之前運行。例如,使用此代碼:javascript動畫:爲什麼下一行在動畫完成之前運行?

this.slideTo = function(x,y) { 
    var originalStyle = this.element.style.cssText; 

    var endX = x; 
    var endY = y; 
    var pos = this.getPosition(); 
    var startX = pos.x; 
    var startY = pos.y; 
    var distX = x - pos.x; 
    var distY = y - pos.y; 
    var totalDistance = Math.sqrt((distX*distX) + (distY*distY)); 
    var count = 0; 
    var done = false; 

    animate(this.element); 
    function animate(element) {   
     count += 5; 
     var curPos = _(element).getPosition(); 
     var curDistX = endX - curPos.x; 
     var curDistY = endY - curPos.y; 
     var curDistance = Math.sqrt((curDistX*curDistX) + (curDistY*curDistY)); 
     var percentDone = count/totalDistance; 
     var moveToX = Math.round((percentDone*distX) + startX); 
     var moveToY = Math.round((percentDone*distY) + startY); 
     _(element).moveTo(moveToX,moveToY); 
     if(percentDone <= 1) { 
      setTimeout(function(){animate(element);},1); 
     } else { 
      done = true; 
     } 
    } 
    console.log(done); 

    this.element.style.cssText = originalStyle; 
} 

控制檯顯示爲false,因爲它在動畫完成之前運行。我該如何解決這個問題?順便說一句:這是在鼠標事件上調用。這有什麼關係嗎?

+0

因爲* setTimeout *異步運行,下列代碼行將立即運行y,* setTimeout *沒有停頓。它在函數完成後運行。 – RobG

回答

0

嘗試下一點點改變的代碼:

this.slideTo = function(x,y) { 
    var originalStyle = this.element.style.cssText; 

    var endX = x; 
    var endY = y; 
    var pos = this.getPosition(); 
    var startX = pos.x; 
    var startY = pos.y; 
    var distX = x - pos.x; 
    var distY = y - pos.y; 
    var totalDistance = Math.sqrt((distX*distX) + (distY*distY)); 
    var count = 0; 
    var done = false; 

    function restoreState(element) { 
     element.style.cssText = originalStyle; 
     /// .... 
    } 

    function animate(element) {   
     count += 5; 
     var curPos = _(element).getPosition(); 
     var curDistX = endX - curPos.x; 
     var curDistY = endY - curPos.y; 
     var curDistance = Math.sqrt((curDistX*curDistX) + (curDistY*curDistY)); 
     var percentDone = count/totalDistance; 
     var moveToX = Math.round((percentDone*distX) + startX); 
     var moveToY = Math.round((percentDone*distY) + startY); 
     _(element).moveTo(moveToX,moveToY); 
     if(percentDone <= 1) { 
      setTimeout(function(){animate(element);},1); 
     } else { 
      done = true; 
      restoreState(element); 
     } 
    } 

    animate(this.element); 
} 
2

它不工作,因爲JS,特別是setTimeout是異步的 - 也就是說,它不會阻塞(sleep/wait/etc)。你基本上設置了超時時間,然後繼續執行其餘的代碼。 JS在時間流逝時調用你的函數,而且沒有做任何事情。

大多數情況下,您可以通過傳遞動畫完成時調用的回調(而不是同時設置done,這將是直接的方法)來解決此問題。

0

總之,setTimeout的不停止執行你的代碼 - 它只是運行有問題的函數在給定超時後:

var a = 'now'; 
function go(){ a = 'later'; }; 
setTimeout(go, 50); 
console.log(a); // 'now' 
setTimeout(function(){ console.log(a); },51); // 'later' 

你想要使用回調模式:

function animate(element, callback){ 
    // do some stuff 
    if(stuffDone){ 
    callback(); 
    } 
} 
animate(element, function(){console.log(whatever); }); 
相關問題