web-dev-qa-db-fra.com

Comment utiliser requestAnimationFrame?

Je suis novice en animation, mais j'ai récemment créé une animation en utilisant setTimeout. Le FPS était trop bas, j'ai donc trouvé une solution pour utiliser requestAnimationFrame, décrite dans ce lien .

Jusqu'à présent, mon code est:

//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);
    })();

Cela s'arrête pendant la première image. J'ai une fonction de rappel requestAnimFrame(animloop); dans la fonction chopElement.

Existe-t-il également un guide plus complet sur l'utilisation de cette API?

49
einstein

Attention! Cette question n'est pas sur la meilleure façon de shim requestAnimFrame. Si vous recherchez cela, passez à toute autre réponse sur cette page.


Vous avez été trompé par l'insertion automatique de points-virgules. Essaye ça:

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

javascript place automatiquement un point-virgule derrière votre instruction return. Il le fait car il est suivi d'une nouvelle ligne et la ligne suivante est une expression valide. En fait, il se traduit par:

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

Ce code renvoie undefined et n'exécute jamais le code derrière l'instruction return. Alors window.requestAnimFrame est undefined. Lorsque vous l'appelez dans animloop, le javascript génère une erreur et arrête l'exécution. Vous pouvez résoudre le problème en mettant l'expression entre parenthèses.

Puis-je recommander le Chrome outils de développement ou firebug pour inspecter l'exécution javascript. Avec ces outils, vous auriez vu l'erreur. Vous devriez procéder au débogage comme suit (je suppose que Chrome):

  1. Exécutez le code (cela produit des résultats inattendus)
  2. Ouvrez les outils de développement (clic droit -> Inspecter l'élément) Vous verrez un x rouge dans la barre d'état à droite (cela signifie qu'il y a une erreur dans l'exécution)
  3. Ouvrez l'onglet console
  4. Tu verras
    TypeError non détecté: la propriété 'requestAnimFrame' de l'objet [objet DOMWindow] n'est pas une fonction
  5. Tapez dans la console: window.requestAnimFrame et appuyez sur Entrée, vous verrez que c'est undefined. Vous savez maintenant que le problème n'est en fait pas lié à requestAnimationFrame et que vous devez vous concentrer sur la première partie de votre code.
  6. Il s'agit maintenant de restreindre le code jusqu'au point où il renvoie quelque chose. C'est la partie difficile et si vous ne le trouvez toujours pas à ce stade, vous voudrez peut-être vous tourner vers Internet pour obtenir de l'aide.

Aussi, regardez cette vidéo pour quelques bonnes pratiques dans l'écriture de javascript, il mentionne également l'insertion automatique de points-virgules.

79
Jan
 /*
  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
}

Jetez un œil à l'exemple jsfiddle ci-dessous; Cela illustre clairement ce que je veux dire;

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

J'espère que cela t'aides!

8
Gokhan Tank

"Limitation intelligente afin que l'événement ne soit pas déclenché plus de fois que l'écran ne peut repeindre le changement:

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
vsync