Как использовать requestAnimationFrame? - PullRequest
49 голосов
/ 09 апреля 2011

Я новичок в анимации, но недавно я создал анимацию, используя setTimeout.FPS был слишком низким, поэтому я нашел решение использовать 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);
    })();

Это останавливается во время первого кадра.У меня есть функция обратного вызова requestAnimFrame(animloop); в функции chopElement.

Кроме того, есть ли более подробное руководство по использованию этого API?

Ответы [ 3 ]

79 голосов
/ 09 апреля 2011

Внимание! Этот вопрос не о лучшем способе шимма 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 и никогда не выполняет код за оператором возврата. Так что window.requestAnimFrame это undefined. Когда вы вызываете его в animloop, JavaScript выдает ошибку и останавливает выполнение. Вы можете решить эту проблему, заключив выражение в скобки.

Могу ли я порекомендовать инструменты разработчика Chrome или firebug для проверки выполнения JavaScript. С этими инструментами вы бы увидели ошибку. Вы должны отладить его следующим образом (я предполагаю, что Chrome):

  1. Выполнить код (он дает неожиданные результаты)
  2. Откройте инструменты разработчика (щелкните правой кнопкой мыши -> Проверить элемент) Вы увидите красный х в строке состояния справа (это означает, что при выполнении произошла ошибка)
  3. Открыть вкладку консоли
  4. Вы увидите
    Uncaught TypeError: Свойство 'requestAnimFrame' объекта [объект DOMWindow] не является функцией
  5. Введите в консоли: window.requestAnimFrame и нажмите Enter, вы увидите, что это undefined. Теперь вы знаете, что проблема на самом деле не связана с requestAnimationFrame и что вам следует сосредоточиться на первой части кода.
  6. Теперь нужно сузить код до точки, где он что-то возвращает. Это сложная часть, и если вы до сих пор не нашли ее, возможно, вы захотите обратиться к Интернету за дополнительной помощью.

Кроме того, посмотрите это видео за некоторыми хорошими практиками в написании javascript, он также упоминает злую автоматическую вставку точек с запятой.

8 голосов
/ 06 августа 2013
 /*
  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/

Надеюсь, это поможет!

0 голосов
/ 18 марта 2014

"Интеллектуальное регулирование, чтобы событие не срабатывало чаще, чем экран может перерисовать изменение:

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; }
...