2011-04-09 47 views
48

我是新來的動畫,但我最近使用setTimeout創建了一個動畫。 FPS太低了,所以我找到了使用​​的解決方案,在link中有描述。如何使用requestAnimationFrame?

到目前爲止,我的代碼是:

//shim layer with setTimeout fallback 
    window.requestAnimFrame = (function(){ 
     return 
      window.requestAnimationFrame  || 
      window.webkitRequestAnimationFrame || 
      window.mozRequestAnimationFrame || 
      window.oRequestAnimationFrame  || 
      window.msRequestAnimationFrame  || 
      function(/* function */ callback){ 
       window.setTimeout(callback, 1000/60); 
      }; 
    })(); 
    (function animloop(){ 
     //Get metrics 
     var leftCurveEndX = finalLeft - initialLeft; 
     var leftCurveEndY = finalTop + finalHeight - initialTop; 
     var rightCurveEndX = finalLeft + finalWidth - initialLeft - initialWidth; 
     var rightCurveEndY = leftCurveEndY; 

     chopElement(0, 0, 0, 0, leftCurveEndX, leftCurveEndY, rightCurveEndX, rightCurveEndY);//Creates a new frame 
     requestAnimFrame(animloop); 
    })(); 

這在第一幀停止。我在chopElement函數中有一個回調函數requestAnimFrame(animloop);

另外,有沒有更徹底的使用這個API的指南?

+3

你爲什麼用‘jQuery的’標籤這個這個問題有 – Jan 2011-04-09 14:47:10

+3

作爲一般規則,在JS中返回時要非常小心,如果在返回後刪除換行符,這將起作用 – 2011-04-09 16:44:03

回答

76

警告!這個問題不是關於墊片的最佳方式requestAnimFrame。如果您正在尋找,請轉到本頁面上的任何其他答案。


你被自動分號插入欺騙了。試試這個:

window.requestAnimFrame = function(){ 
    return (
     window.requestAnimationFrame  || 
     window.webkitRequestAnimationFrame || 
     window.mozRequestAnimationFrame || 
     window.oRequestAnimationFrame  || 
     window.msRequestAnimationFrame  || 
     function(/* function */ callback){ 
      window.setTimeout(callback, 1000/60); 
     } 
    ); 
}(); 

javascript會自動在您的return聲明後面加分號。它這樣做是因爲它後面跟着一個換行符,而下一行是一個有效的表達式。事實上,它被翻譯成:

return; 
window.requestAnimationFrame  || 
window.webkitRequestAnimationFrame || 
window.mozRequestAnimationFrame || 
window.oRequestAnimationFrame  || 
window.msRequestAnimationFrame  || 
function(/* function */ callback){ 
    window.setTimeout(callback, 1000/60); 
}; 

此代碼返回undefined,從不執行return語句後面的代碼。所以window.requestAnimFrameundefined。當你在animloop中調用它時,javascript會產生錯誤並停止執行。將表達式括在括號中可以解決問題。

我可以推薦使用Chrome開發人員工具或firebug來檢查javascript的執行情況嗎?有了這些工具,你會看到錯誤。你應該去如下(我假設鉻)調試它:

  1. 執行代碼(它會產生意想不到的效果)
  2. 打開開發者工具(右鍵 - >檢查元素) 你會看到在右側的狀態欄上一個紅色的X(這意味着在執行中的錯誤)
  3. 打開控制檯選項卡
  4. 你會看到
    Uncaught TypeError: Property 'requestAnimFrame' of object [object DOMWindow] is not a function
  5. 鍵入控制檯:window.requestAnimFrame,然後按回車,你會看到它是undefined。現在您知道問題實際上與​​無關,您應該專注於代碼的第一部分。
  6. 現在,它是縮小代碼的範圍,直到它返回的東西。這是一個困難的部分,如果您在這一點上仍然沒有找到它,您可能需要轉向互聯網尋求更多幫助。

另外,看看this video爲寫一些JavaScript的好手法,他還提到了邪惡的自動分號插入。

+3

很好知道,確實很棘手 – pimvdb 2011-04-09 18:01:39

+0

使用此方法的事件如'scroll在不支持requestA的瀏覽器中調整或調整大小nimationFrame'將始終觸發回調,而不是像預期的那樣,因爲setTimeout將不斷被觸發,創建新的定時器並逐個運行它們。節氣門方法更適合補償。另外,你不需要在每個全局之前編寫'window' ......這是多餘的。 – vsync 2014-03-17 20:12:22

8
/* 
    Provides requestAnimationFrame in a cross browser way. 
    http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 
*/ 

if (!window.requestAnimationFrame) { 

    window.requestAnimationFrame = (function() { 

     return window.webkitRequestAnimationFrame || 
      window.mozRequestAnimationFrame || // comment out if FF4 is slow (it caps framerate at ~30fps: https://bugzilla.mozilla.org/show_bug.cgi?id=630127) 
     window.oRequestAnimationFrame || 
      window.msRequestAnimationFrame || 
      function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) { 

       window.setTimeout(callback, 1000/60); 

     }; 

    })(); 

} 

animate(); 

function animate() { 
    requestAnimationFrame(animate); 
    draw(); 
} 

function draw() { 
    // Put your code here 
} 

看看下面的jsfiddle例子;它清楚地說明了我的意思;

http://jsfiddle.net/XQpzU/4358/light/

希望這有助於!

+1

您在animate()中的調用使用錯誤的函數名稱。 Paul確實在他的例子中使用了requestAnimFrame,但是你正在填充requestAnimationFrame(我更喜歡btw)。易於修復。 – Micros 2013-09-12 13:45:13

+0

感謝您的評論,Micros!我編輯過它。我更喜歡使用你喜歡的長命名函數。我認爲這種習慣來自我使用obj-c語言:) – 2013-09-25 03:58:03

0

「智能節流所以該事件將不會被解僱更多的時間比屏幕可以重繪變化:

var requestFrame = window.requestAnimationFrame || 
 
        window.webkitRequestAnimationFrame || 
 
        // polyfill - throttle fall-back for unsupported browsers 
 
        (function() { 
 
         var throttle = false, 
 
          FPS = 1000/60; // 60fps (in ms) 
 
     
 
         return function(CB) { 
 
         if(throttle) return; 
 
         throttle = true; 
 
         setTimeout(function(){ throttle = false }, FPS); 
 
         CB(); // do your thing 
 
         } 
 
        })(); 
 

 
///////////////////////////// 
 
// use case: 
 

 
function doSomething() { 
 
    console.log('fired'); 
 
} 
 

 
window.onscroll = function() { 
 
    requestFrame(doSomething); 
 
};
html, body{ height:300%; } 
 
body::before{ content:'scroll here'; position:fixed; font:2em Arial; }

+0

我不知道,但FPS可能應該是1000/60 60fps – Ampersanda 2018-02-26 13:56:51

+0

@Ampersanda - 謝謝,我的錯誤。現在已經修復了 – vsync 2018-02-27 14:11:26

+0

Sweet, 嘿vsync你知道嗎?還有一些關於使用requestAnimationFrame緩動滾動頁面的問題? – Ampersanda 2018-02-28 05:42:14

相關問題