2011-04-09 7 views
48

Soy nuevo en la animación, pero recientemente he creado una animación usando setTimeout. El FPS era demasiado bajo, así que encontré una solución para usar requestAnimationFrame, que se describe en este link.Cómo utilizar requestAnimationFrame?

Hasta ahora, mi código es:

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

Esto evita que durante la primera trama. Tengo una función de devolución de llamada requestAnimFrame(animloop); en la función chopElement.

Además, ¿hay una guía más completa para usar esta API?

+3

¿Por qué etiquetar esto con 'jquery' a esta pregunta tiene nada que ver con eso. – Jan

+3

Como regla general, tenga mucho cuidado con los retornos en JS, si elimina la nueva línea después de la devolución, esto funcionará. –

Respuesta

76

¡Advertencia! Esta pregunta no es sobre la mejor manera de calzarrequestAnimFrame. Si está buscando eso, continúe con cualquier otra respuesta en esta página.


Usted fue engañado por la inserción automática de punto y coma. Prueba esto:

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

javascript automáticamente pone un punto y coma detrás de la declaración return. Hace esto porque es seguido por una nueva línea y la siguiente línea es una expresión válida. De hecho, se traduce a:

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

Este código devuelve undefined y nunca ejecuta el código detrás de la instrucción de retorno. Entonces window.requestAnimFrame es undefined. Cuando lo llama en animloop, el javascript produce un error y detiene la ejecución. Puede resolver el problema al encerrar la expresión entre paréntesis.

Puedo recomendar las herramientas de desarrollador de Chrome o Firebug para inspeccionar la ejecución de JavaScript. Con estas herramientas, habrías visto el error. Hay que ir sobre la depuración de la siguiente manera (estoy asumiendo Chrome):

  1. ejecutar el código (que produce resultados inesperados)
  2. Abra las herramientas de desarrollo (click derecho -> Inspeccionar elemento) Verá una x roja en la barra de estado en la parte derecha (esto significa que hay un error en la ejecución)
  3. Abrir la pestaña de la consola
  4. verá
    Uncaught TypeError: Property 'requestAnimFrame' of object [object DOMWindow] is not a function
  5. Type en la consola: window.requestAnimFrame y pulse enter, se quiere ver es undefined. Ahora ya sabe que el problema de hecho no está relacionado con requestAnimationFrame y que debe concentrarse en la primera parte de su código.
  6. Ahora se trata de reducir el código hasta el punto en que devuelve algo. Esta es la parte difícil y si aún no lo encuentras en este punto, es posible que desees recurrir a Internet para obtener más ayuda.

Además, mira this video para algunas buenas prácticas en la escritura de javascript, También menciona la inserción de punto y coma malvado automático.

+3

Es bueno saberlo, de hecho es complicado. – pimvdb

+0

usando este método con eventos como 'scroll 'o' resize' en navegadores que no admiten 'requestA nimationFrame' activará la devolución de llamada todo el tiempo, y no de la manera prevista, porque el setTimeout se activará constantemente, creando nuevos temporizadores y ejecutándolos uno después del otro. un método de acelerador es más adecuado para compensar. Además, no es necesario que escriba 'window' antes de cada global ... es redundante. – vsync

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 
} 

Eche un vistazo al siguiente ejemplo jsfiddle; Ilustra claramente lo que quiero decir;

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

Espero que esto ayude!

+1

Su llamada dentro de animate() está utilizando un nombre de función incorrecto. Paul usa requestAnimFrame en su ejemplo de hecho, pero estás ajustando requestAnimationFrame (que me gusta más por cierto). Fácil de arreglar – Micros

+0

Gracias por el comentario, Micros! Lo he editado. En su mayoría prefiero usar funciones de nombres largos como te gusta. Creo que el hábito vino de usar el lenguaje obj-c :) –

0

"estrangulamiento inteligente por lo que el evento no será despedida más veces que la pantalla se puede volver a pintar el cambio:?

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

No lo sé, pero el FPS tal vez debería ser 1000/60 como 60fps – Ampersanda

+0

@Ampersanda - gracias, mi error. ahora fijo – vsync

+0

Sweet, Hey vsync ¿sabes o algo sobre cómo facilitar la página de desplazamiento con requestAnimationFrame? – Ampersanda