Red de conocimiento informático - Problemas con los teléfonos móviles - Uso de requestAnimationFrame y cancelAnimationFrame

Uso de requestAnimationFrame y cancelAnimationFrame

En las aplicaciones web, hay muchas formas de implementar efectos de animación, como el temporizador setTimeout en Javascript, transiciones y animaciones en css3 y lienzo en html5. Además, HTML5 también proporciona una API específica para solicitar animación, a saber, requestAnimationFrame, que es solo un cuadro de animación de solicitud.

Para comprender el principio detrás de requestAnimationFrame, primero debemos comprender varios conceptos relacionados:

Cuando la página se minimiza o se cambia a la pestaña de fondo, la página no es visible y el navegador activará el evento de cambio de visibilidad y establecerá la propiedad document.hidden en verdadero. Cuando se cambia al estado de visualización, la página es visible, lo que también activa el evento de cambio de visibilidad y establece la propiedad document.hidden en falso.

Es decir, la velocidad a la que se actualiza la imagen en pantalla, es decir, el número de veces que aparece la imagen en pantalla por segundo, en Hercios (Hz). Para una computadora portátil general, esta frecuencia es de alrededor de 60 Hz. La configuración de este valor se ve afectada por la resolución de la pantalla, el tamaño de la pantalla y la tarjeta gráfica.

Basándonos en el principio anterior, sabemos que la imagen que ves frente a ti se actualiza 60 veces por segundo. Debido a que la frecuencia de actualización es alta, no se siente refrescante. La esencia de la animación es permitir que las personas vean el efecto visual de los cambios provocados por la imagen que se actualiza. Este cambio debe ser una transición coherente y fluida. Entonces, ¿cómo podemos lograr este efecto? Una pantalla con una frecuencia de actualización de 60 Hz se actualiza cada 16,7 ms. Antes de que se actualice la pantalla, movemos la posición de la imagen un píxel hacia la izquierda, que es 1 px. De esta manera, la posición de la imagen impresa en la pantalla es 1px peor que la última vez, por lo que verás la imagen moverse debido al efecto de retención visual de nuestros ojos humanos, la impresión de que la imagen en la posición actual permanece; en el cerebro no desaparece, y luego mueve la imagen a la siguiente posición, para que veas que la imagen se mueve suavemente, esta es la animación formada en el efecto visual.

De forma asincrónica, la función pasada se llama antes de volver a dibujarla.

(2) El valor de retorno handlerId es un número entero mayor que 0 definido por el navegador, que identifica de forma única la posición de la función de devolución de llamada en la lista.

Después de comprender los conceptos anteriores, no es difícil descubrir que setTimeout en realidad cambia la posición de la imagen estableciendo un intervalo para lograr el efecto de animación. Sin embargo, la animación implementada por seTimeout aparecerá atascada y nerviosa en algunas computadoras de gama baja. Hay dos razones para este fenómeno:

El tiempo de ejecución de setTimeout es incierto. En Javascript, la tarea setTimeout se coloca en una cola asincrónica. Solo después de ejecutar la tarea en el hilo principal se verificará si la tarea en la cola necesita comenzar a ejecutarse, por lo que el tiempo de ejecución real de setTimeout generalmente es posterior a su tiempo. tiempo.

La frecuencia de actualización se ve afectada por la resolución y el tamaño de la pantalla, por lo que la frecuencia de actualización de la pantalla de diferentes dispositivos puede ser diferente. setTimeout solo puede establecer un intervalo de tiempo fijo, que no es necesariamente el mismo que el de la pantalla. tiempo de actualización.

Las dos situaciones anteriores harán que el ritmo de ejecución de setTimeout sea inconsistente con el ritmo de actualización de la pantalla, lo que provocará la pérdida de fotogramas. Entonces, ¿por qué un ritmo inconsistente provoca pérdida de fotogramas?

En primer lugar, debe comprender que la implementación de setTimeout solo cambia los atributos de la imagen en la memoria, y este cambio no se actualizará en la pantalla hasta la próxima actualización de la pantalla. Si los dos pasos son inconsistentes, puede hacer que se omita la operación de un cuadro intermedio y que la imagen del siguiente cuadro se actualice directamente. Supongamos que la pantalla se actualiza cada 16,7 ms y setTimeout configura la imagen para que se mueva 1 px hacia la izquierda cada 10 ms. Se producirá el siguiente proceso de dibujo:

0 ms: la pantalla no se actualiza, esperando, setTimeout está. no ejecutado, esperando;

10ms: La pantalla no se actualiza y está esperando. setTimeout inicia la ejecución y establece el atributo de imagen left = 1px;

16,7 ms: la pantalla comienza a actualizarse y la imagen en la pantalla se mueve 1px hacia la izquierda.

setTimeout no se ejecuta, todavía está esperando.

20.º ms: La pantalla aún no se ha actualizado y está esperando. setTimeout comienza a ejecutarse, configurando left = 2px

30.º ms: la pantalla aún no se ha actualizado y está esperando. setTimeout comienza a ejecutarse, configurando left = 3px

33.4ms: la pantalla comienza a actualizarse y la imagen en la pantalla se mueve 3px hacia la izquierda. setTimeout no se ejecuta, todavía está esperando.

Como se puede ver en el proceso de dibujo anterior, la pantalla no actualiza el marco izquierdo = 2px y la imagen salta directamente desde la posición de 1px a la posición de 3px. Este es el fenómeno de pérdida de cuadros, que hará que la animación se congele.

En comparación con setTimeout, la mayor ventaja de requestAnimationFrame es que el sistema determina el tiempo de ejecución de la función de devolución de llamada. Específicamente, si la frecuencia de actualización de la pantalla es de 60 Hz, entonces la función de devolución de llamada se ejecuta cada 16,7 ms. Si la frecuencia de actualización es de 75 Hz, entonces el intervalo de tiempo se convierte en 1000/75 = 13,3 ms. En otras palabras, el ritmo de requestAnimationFrame sigue el sistema. Ritmo refrescante. Se puede garantizar que la función de devolución de llamada solo se ejecute una vez en cada intervalo de actualización de la pantalla, de modo que no cause pérdida de fotogramas ni retrasos en la animación.

La llamada a esta API es muy sencilla, como se muestra a continuación:

Además, requestAnimationFrame tiene las siguientes dos ventajas:

Ahorro de energía de la CPU: cuando el La página está oculta o minimizada, setTimeout aún realiza tareas de animación en segundo plano. Debido a que la página es invisible o no está disponible en este momento, actualizar la animación no tiene sentido y es una completa pérdida de recursos de la CPU. requestAnimationFrame es completamente diferente. Cuando el procesamiento de la página no está activado, el sistema también suspenderá la tarea de actualización de la pantalla de la página, por lo que el requestAnimationFrame que sigue el ritmo del sistema también dejará de procesarse. Cuando se activa la página, la animación continuará desde la última parada, lo que ahorra efectivamente la sobrecarga de la CPU.

Limitación de funciones: en eventos de alta frecuencia (cambio de tamaño, desplazamiento, etc.), para evitar que la función se ejecute varias veces dentro de un intervalo de actualización, use requestAnimationFrame para ejecutar la función solo una vez por actualización. intervalo, que no solo puede garantizar la fluidez, sino también ahorrar mejor el costo de ejecución de la función. No tiene sentido ejecutar la función varias veces dentro de un intervalo de actualización, ya que la pantalla se actualiza cada 16,7 ms y no se reflejarán varios dibujos en la pantalla.