Los temporizadores siempre han sido la tecnología central de la animación JavaScript. La clave para escribir un bucle de animación es saber cuánto dura el tiempo de retraso. Por un lado, el intervalo del bucle debe ser lo suficientemente corto para que los diferentes efectos de animación parezcan fluidos; por otro lado, el intervalo del bucle debe ser lo suficientemente largo para garantizar que el navegador tenga la capacidad de representar los cambios resultantes;
La frecuencia de actualización de la mayoría de los monitores de computadora es de 60 Hz, lo que equivale aproximadamente a 60 redibujados por segundo. La mayoría de los navegadores limitarán las operaciones de redibujado a no más que la frecuencia de redibujado de la pantalla, porque incluso más allá de esa frecuencia la experiencia del usuario no mejorará. Por lo tanto, el intervalo de bucle óptimo para la animación más fluida es 1000 ms/60, lo que equivale aproximadamente a 16,6 ms.
El problema con setTimeout y setInterval es que no son precisos. Su mecanismo operativo interno determina que el parámetro de intervalo de tiempo en realidad solo especifica el tiempo para agregar el código de animación a la cola de subprocesos de la interfaz de usuario del navegador para esperar la ejecución. Si se han agregado otras tareas al frente de la cola, el código de animación debe esperar hasta que se complete la tarea anterior antes de ejecutarla.
requestAnimationFrame utiliza el intervalo de tiempo del sistema para mantener la mejor eficiencia de dibujo. No provocará un dibujo excesivo ni aumentará la sobrecarga porque el intervalo es demasiado corto. Tampoco provocará que la animación se atasque y no sea fluida porque el intervalo es demasiado largo, lo que permite. Se pueden lograr varios efectos de animación de páginas web. Existe un mecanismo de actualización unificado para ahorrar recursos del sistema, mejorar el rendimiento del sistema y mejorar los efectos visuales.
CaracterísticasEl método requestAnimationFrame toma una devolución de llamada como parámetro, y la función de devolución de llamada se pasará en un parámetro, DOMHighResTimeStamp, que indica el momento en que se activa la función de devolución de llamada actualmente ordenada por requestAnimationFrame(). El valor de retorno es un ID de solicitud, que representa un identificador único en la lista de devolución de llamada. Este valor se puede pasar a window.cancelAnimationFrame() para cancelar la función de devolución de llamada.
requestID = ventana.requestAnimationFrame(devolución de llamada);
Con esta API, se pueden ejecutar ciertos códigos durante la siguiente renderización para evitar desencadenar una gran cantidad de reflujos en un corto período de tiempo.
Por ejemplo, la función de devolución de llamada del evento de desplazamiento de página (desplazamiento) es muy adecuada para usar esta API y pospone la operación de devolución de llamada hasta la próxima representación. Sin embargo, debe tenerse en cuenta que requestAnimationFrame no administra funciones de devolución de llamada, es decir, llamar a requestAnimationFrame con la misma función de devolución de llamada varias veces antes de que se ejecute la devolución de llamada hará que la devolución de llamada se ejecute varias veces en el mismo marco. La forma más sencilla es utilizar una función de limitación para resolver este problema, o puede encontrar una manera de tener solo una misma función de devolución de llamada en la cola de requestAnimationFrame:
dejar programadoAnimationFrame = false;document.body.onscroll = () => { if (programadoAnimationFrame) return; programadoAnimationFrame = true;
Por supuesto, el mejor escenario de aplicación sigue siendo la animación de cuadros, que puede optimizar en gran medida el rendimiento.
Preguntas de la entrevista Cómo renderizar decenas de miles de datos sin quedarse atascado en la interfazEsta pregunta examina cómo representar datos sin bloquear la página. Es decir, no puede representar decenas de miles de elementos a la vez, pero debe representar parte del DOM a la vez. Luego puede actualizarlo cada 16 ms a través de requestAnimationFrame.
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta nombre=viewport content=ancho=ancho del dispositivo, escala inicial=1.0> <meta http-equiv=X-UA -Contenido compatible=es decir=edge> <title>Documento</title></head><body> <ul>Control</ul> <script> setTimeout(() => { // Inserte 100.000 datos const total = 100000 // Inserte 20 datos a la vez. Si cree que el rendimiento no es bueno, reduzca const once = 20 // ¿Cuántas veces se necesitarán para representar los datos const loopCount = total /? una vez let countOfRender = 0 let ul = document. querySelector(ul); function add() { // Optimiza el rendimiento, la inserción no provocará reflujo const fragment = document.createDocumentFragment() for (let i = 0; i < una vez; i++) { const li = document.createElement(li); li.innerText = Math.floor(Math.random() * total); fragment.appendChild(li); 1; bucle(); } función bucle() { if (countOfRender < loopCount) { ventana.requestAnimationFrame(agregar); bucle(); }, 0); </script></body></html>compatibilidad
Algunos navegadores antiguos no admiten esta API. Para utilizar esta API, puede personalizar este método y montarlo debajo de la ventana:
(función() { var lastTime = 0; var proveedores = ['webkit', 'moz']; for(var x = 0; x < proveedores.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = ventana[proveedores[x]+'RequestAnimationFrame']; ventana.cancelAnimationFrame = ventana[proveedores[x]+'CancelAnimationFrame'] || ventana[vendedores[x]+'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback) { var currTime = new Date().getTime(); 0, 16 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; devolver id };
Lo anterior es el contenido completo de este artículo. Espero que sea útil para el estudio de todos. También espero que todos apoyen VeVb Wulin Network.