2010-05-30 15 views
26

Al escribir una animación de JavaScript, por supuesto crea un bucle usando setInterval (o setTimeout repetido). Pero, ¿cuál es la mejor demora para usar en la (s) llamada (s) setInterval/setTimeout?¿Cómo determinar el mejor "framerate" (setInterval delay) para usar en un bucle de animación de JavaScript?

En el jQuery API page for the .animate() function, el usuario "fbogner" dice:

Sólo si alguien está interesado: Las animaciones son "prestados" por medio de un setInterval con un tiempo de 13 ms. ¡Esto es bastante rápido! El intervalo más rápido posible de Chrome es de aproximadamente 10 ms. Todos los demás navegadores "muestras" a aproximadamente 20-30 ms.

Cualquier idea de cómo jQuery decidido a utilizar este número específico?


Bounty. Espero que alguien con conocimiento del código fuente detrás de Chromium o Firefox pueda proporcionar algunos hechos concretos que puedan respaldar la decisión de un framerate específico. O tal vez una lista de animaciones (o marcos) y sus retrasos. Creo que esto constituye una oportunidad interesante para investigar un poco.


interesante - Me tomó el tiempo para mirar a Pac-Man fuente de Google para ver lo que hicieron. Configuran un conjunto de FPS posibles (90, 45, 30), comienzan en el primero, y luego en cada cuadro comprueban la "lentitud" del fotograma (cantidad que el fotograma superó el tiempo asignado). Si la lentitud excede 50 ms 20 veces, la velocidad de fotogramas se rebaja al siguiente en la lista (90 -> 45, 45 -> 30). Parece que la velocidad de fotogramas nunca se levanta una copia de seguridad, presumiblemente porque el juego es tan efímero que no valdría la pena codificarlo.

Ah, y el retraso setInterval por supuesto se establece en 1000/framerate. De hecho, usan setInterval y no repiten setTimeouts.

¡Creo que esta función de velocidad de fotogramas dinámica es bastante clara!

Respuesta

16

Me atrevo a decir que una parte sustancial de los usuarios de la web utilizan monitores que actualizan a 60Hz, lo que se traduce en un cuadro cada 16.66ms. Entonces, para que el monitor sea el cuello de botella, necesita producir cuadros a más velocidad que 16,66 ms.

Existen dos razones por las que elegiría un valor como 13ms. Primero, el navegador necesita un poco de tiempo para volver a pintar la pantalla (en mi experiencia, nunca menos de 1 ms). Lo cual lo pone en, por ejemplo, actualizando cada 15 ms, que resulta ser un número muy interesante: la resolución del temporizador estándar en Windows es de 15 ms (consulte John Resig's blog post). Sospecho que una animación bien escrita de 15ms se parece mucho a la misma en una amplia variedad de navegadores/sistemas operativos.

FWIW, fbogner es llano incorrecto sobre el sistema que enciende de los navegadores de Chrome no Intervalo cada 20-30ms. Escribí un test para medir la velocidad del disparo setInterval, y tengo estos números:

  • Chrome - 4 ms
  • Firefox 3.5 - 15 ms
  • IE6 - 15 ms
  • IE8 - 15 ms
+0

El enlace de la publicación de blog de '' John Resig '' indica una URL incorrecta –

+0

La publicación del blog de John Resig debería quizás apunte a http://ejohn.org/blog/accuracy-of-javascript-time/ –

+0

Corregido - gracias. –

1

No conoce el razonamiento detrás del tiempo de intervalo de jQuery, ya que 13ms se traduce a 80 fps, que es muy rápido. El fps "estándar" que se usa en las películas y tal es de 25 fps y es lo suficientemente rápido para que el ojo humano no note ningún tipo de nerviosismo. 25 fps se traduce a 40 ms, por lo que para responder a su pregunta: cualquier cantidad inferior a 40 ms es suficiente para una animación.

+0

Jitter es notable a 30 fps para juegos. Cuando has estado jugando a 200 fps y se reduce a 40 fps, es notable. Por otra parte, eso podría tener que ver con la actualización del monitor ... Por cierto, cuando los navegadores procesan ¿usan sincronización vertical? Si es así, estás prácticamente bloqueado a 50/60 fps ... – Warty

+6

las películas se capturan a 24 fps, lo que es lo suficientemente lento como para capturar el desenfoque de movimiento natural. tu cerebro suaviza todo cuando ves una película. la animación renderizada dinámicamente no tendrá el beneficio de ser capturada de la vida real. – lincolnk

3

Al realizar bucles para animaciones, es mejor que encuentre un equilibrio entre la velocidad del bucle y la cantidad de trabajo que se necesita hacer.

Por ejemplo, si desea deslizar un div en la página en un segundo, es un efecto agradable y oportuno. Se saltea las coordenadas y tiene un tiempo de bucle razonablemente rápido para que el efecto sea notable, pero no nervioso.

Por lo tanto, es una cuestión de prueba y error (al tener que tener en cuenta el trabajo, el tiempo y la capacidad del navegador). Por lo tanto, no solo se ve bien en un navegador.

2

Se ha probado el número indicado por fbogner. Los navegadores aceleran la actividad js hasta cierto punto para que se pueda usar todo el tiempo.

Si su javascript fuera posible ejecutar cada 5msec, el tiempo de ejecución del navegador tendría mucho menos tiempo de CPU para actualizar el renderizado o reaccionar ante la entrada del usuario (clics) porque javascript-execution bloquea el navegador.

Creo que los desarrolladores de Chrome le permiten ejecutar su javascript a intervalos mucho más cortos que los otros navegadores porque su V8-Javascript-Engine compila el JavaScript y por lo tanto se ejecuta más rápido y el navegador no se bloqueará siempre que código js interpretado.

Pero el motor no sólo es mucho más rápido para permitir intervalos más cortos los desarrolladores ciertamente han probado que es el mejor intervalo más corto posible para permitir intervalos cortos y no bloquear el navegador para que a largo

+0

¿Quién es fbogner? – Ricket

+0

La persona que citó en su pregunta xD –

+0

¡Oh, jaja! Ni siquiera lo recuerdo, desde que escribí esta pregunta hace unas semanas ... – Ricket

5

El pseudo código de esto es la siguiente:

FPS_WANTED = 25 
(just a number, it can be changed while executing, or it can be constant) 

TIME_OF_DRAWING = 1000/FPS_WANTED 
(this is in milliseconds, I believe it is accurate enough) 
(should be updated when FPS_WANTED changes) 

UntilTheUserLeavesTheDrawingApplication() 
{ 

    time1 = getTime(); 
    doAnimation(); 
    time2 = getTime(); 
    animationTime = time2-time1; 

    if (animationTime > TIME_OF_DRAWING) 
    { 
    [the FPS_WANTED cannot be reached] 
    You can: 
    1. Decrease the number of FPS to see if a lower framerate can be achieved 
    2. Do nothing because you want to get all you can from the CPU 
    } 
    else 
    { 
    [the FPS can be reached - you can decide to] 
    1. wait(TIME_OF_DRAWING-animationTime) - to keep a constant framerate of FPS_WANTED 
    2. increase framerate if you want 
    3. Do nothing because you want to get all you can from the CPU 
    } 

} 

por supuesto que puede haber variaciones de esto, pero esto es el algoritmo básico que es válida en cualquier caso de la animación.

+1

+1 gracias por hacerlo simple y comprensible –

Cuestiones relacionadas