2012-08-13 26 views
15

Por lo tanto, tal vez brainfart total aquí. La sintaxis para setInterval() es bastante clara. Haz algo cada x milisegundos. ¿Cómo se puede traducir esto mejor al uso del requestAnimationFrame()?HTML Canvas Interval vs RequestAnimationFrame

Tengo alrededor de 300 objetos y se supone que cada uno debe realizar una secuencia de animación en un determinado intervalo (cada 8, 6, 2, etc. segundos)? ¿Cómo puedo lograr esto usando requestAnimationFrame() que se llama ~ 60 veces por segundo? Probablemente haya una respuesta fácil, yo solo, por mi vida, no puedo entenderlo.

Respuesta

10

requestAnimationFrame es bastante bajo nivel, solo hace lo que ya ha dicho: aproximadamente se llama a 60fps (suponiendo que el navegador puede mantener el ritmo). Por lo general, necesitaría construir algo además de eso, al igual que un motor de juego que tiene un bucle de juego.

En mi motor de juego, tengo este (paraphased/simplificado aquí):

window.requestAnimationFrame(this._doFrame); 

... 

_doFrame: function(timestamp) { 
    var delta = timestamp - (this._lastTimestamp || timestamp); 

    for(var i = 0, len = this.elements.length; i < len; ++i) { 
     this.elements[i].update(delta); 
    } 

    this._lastTimestamp = timestamp; 

    // I used underscore.js's 'bindAll' to make _doFrame always 
    // get called against my game engine object 
    window.requestAnimationFrame(this._doFrame); 
} 

A continuación, cada elemento en mi motor de juego sabe cómo actualizar a sí mismos. En su caso, cada elemento que debe actualizar cada 2, 6, 8 segundos necesario para mantener un registro de cuánto tiempo ha pasado y actualizar en consecuencia:

update: function(delta) { 
    this.elapsed += delta; 

    // has 8 seconds passed? 
    if(this.elapsed >= 8000) { 
      this.elapsed -= 8000; // reset the elapsed counter 
      this.doMyUpdate(); // whatever it should be 
    } 
} 

La API lienzo junto con requestAnimationFrame son bastante bajo nivel, que son el bloques de construcción para cosas como animación y motores de juegos. De ser posible, trataría de usar uno ya existente como cocos2d-js o cualquier otra cosa que exista en estos días.

+0

gracias! esto es más o menos lo que estaba buscando. Un poco más de excavación reveló esto: https://gist.github.com/1002116 que es esencialmente lo que tienes. Creo que mi error fue tratar de hacerlo funcionar dentro de un ciclo principal frente a un ciclo para cada objeto. –

10

Para forzar requestAnimationFrame para que se adhiera a un FPS específico, puede usar ambos a la vez.

var fps = 15; 
function draw() { 
    setTimeout(function() { 
     requestAnimationFrame(draw); 
     // Drawing code goes here 
    }, 1000/fps); 
} 

Un poco raro, pero no es la cosa más confusa del mundo.

También puede utilizar requestAnimationFrame no con FPS pero con el tiempo transcurrido con el fin de dibujar objetos que necesitan ser actualizados en base a la diferencia de tiempo desde la última llamada:

var time; 
function draw() { 
    requestAnimationFrame(draw); 
    var now = new Date().getTime(), 
     dt = now - (time || now); 

    time = now; 

    // Drawing code goes here... for example updating an 'x' position: 
    this.x += 10 * dt; // Increase 'x' by 10 units per millisecond 
} 

Estos dos fragmentos son de this fine article, que contiene detalles adicionales.

¡Buena pregunta por cierto! No creo que haya visto esto respondido en SO tampoco (y estoy aquí demasiado)

+0

también, ¡gracias! el segundo fragmento está cerca de lo que estaba buscando. como dije en el comentario de la primera respuesta, esto parece lo que buscaba: https://gist.github.com/1002116 –

+0

ambas respuestas fueron realmente geniales, ¡realmente lo aprecio! –

+0

requestAnimationFrame envía una marca de tiempo junto con un argumento. En mi experiencia, crear un nuevo objeto Date es mucho más costoso que usar la marca de tiempo proporcionada. –