Подтвердить что ты не робот

Как использовать requestAnimationFrame?

Я новичок в анимации, но недавно создал анимацию с помощью 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?

4b9b3361

Ответ 1

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

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

  • Выполнить код (он дает неожиданные результаты)
  • Откройте инструменты разработчика (щелкните правой кнопкой мыши → Проверить элемент) Вы увидите красный x в строке состояния справа (это означает, что в выполнении есть ошибка).
  • Откройте вкладку консоли
  • Вы увидите
    Uncaught TypeError: свойство 'requestAnimFrame' объекта [object DOMWindow] не является функцией
  • Введите консоль: window.requestAnimFrame и нажмите enter, вы увидите, что она undefined. К настоящему времени вы знаете, что проблема на самом деле не связана с requestAnimationFrame и что вы должны сосредоточиться на первой части вашего кода.
  • Теперь это вопрос сужения кода до того момента, когда он что-то возвращает. Это сложная часть, и если вы все еще не найдете ее в этот момент, вы можете обратиться за помощью в Интернет для получения дополнительной помощи.

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

Ответ 2

 /*
  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/

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

Ответ 3

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

var requestFrame =  window.requestAnimationFrame || 
                    window.webkitRequestAnimationFrame || 
                    // throttle fall-back for unsupported browsers
                    (function(){ 
                        var throttle = false,
                            FPS = 60 / 1000; // time 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); };