Les minuteries ont toujours été la technologie de base de l'animation JavaScript. La clé pour écrire une boucle d’animation est de connaître la durée du temps de retard. D'une part, l'intervalle de boucle doit être suffisamment court pour que les différents effets d'animation semblent fluides ; d'autre part, l'intervalle de boucle doit être suffisamment long pour garantir que le navigateur a la capacité de restituer les modifications résultantes.
Le taux de rafraîchissement de la plupart des écrans d'ordinateur est de 60 Hz, ce qui équivaut à peu près à 60 rafraîchissements par seconde. La plupart des navigateurs limitent les opérations de rafraîchissement à la fréquence de rafraîchissement de l'affichage, car même au-delà de cette fréquence, l'expérience utilisateur ne sera pas améliorée. Par conséquent, l’intervalle de boucle optimal pour l’animation la plus fluide est de 1 000 ms/60, ce qui équivaut approximativement à 16,6 ms.
Le problème avec setTimeout et setInterval est qu'ils ne sont pas précis. Leur mécanisme de fonctionnement interne détermine que le paramètre d'intervalle de temps spécifie simplement le temps nécessaire pour ajouter le code d'animation à la file d'attente des threads de l'interface utilisateur du navigateur pour attendre l'exécution. Si d'autres tâches ont été ajoutées en début de file d'attente, le code d'animation doit attendre que la tâche précédente soit terminée avant de l'exécuter.
requestAnimationFrame utilise l'intervalle de temps du système pour maintenir la meilleure efficacité de dessin. Cela n'entraînera pas de surdessin ni d'augmentation de la surcharge car l'intervalle est trop court. Cela ne provoquera pas non plus le blocage et la fluidité de l'animation car l'intervalle est trop long, ce qui permet. divers effets d'animation de page Web à obtenir. Il existe un mécanisme d'actualisation unifié pour économiser les ressources du système, améliorer les performances du système et améliorer les effets visuels.
CaractéristiquesLa méthode requestAnimationFrame prend un rappel comme paramètre, et la fonction de rappel sera passée dans un paramètre, DOMHighResTimeStamp, indiquant l'heure à laquelle la fonction de rappel actuellement triée par requestAnimationFrame() est déclenchée. La valeur de retour est un ID de demande, qui représente un identifiant unique dans la liste de rappel. Cette valeur peut être transmise à window.cancelAnimationFrame() pour annuler la fonction de rappel.
requestID = window.requestAnimationFrame(callback);
Grâce à cette API, certains codes peuvent être exécutés lors du prochain re-rendu pour éviter de déclencher un grand nombre de reflows dans un court laps de temps.
Par exemple, la fonction de rappel de l'événement de défilement de page (scroll) est très adaptée à l'utilisation de cette API, différant l'opération de rappel jusqu'au prochain rendu. Cependant, il convient de noter que requestAnimationFrame ne gère pas les fonctions de rappel, c'est-à-dire que l'appel de requestAnimationFrame avec la même fonction de rappel plusieurs fois avant l'exécution du rappel entraînera l'exécution du rappel plusieurs fois dans la même trame. Le moyen le plus simple consiste à utiliser une fonction de limitation pour résoudre ce problème, ou vous pouvez trouver un moyen de n'avoir qu'une seule même fonction de rappel dans la file d'attente de requestAnimationFrame :
let ScheduledAnimationFrame = false;document.body.onscroll = () => { if (scheduledAnimationFrame) return;
Bien entendu, le meilleur scénario d’application reste l’animation image, qui peut considérablement optimiser les performances.
Questions d'entretien Comment restituer des dizaines de milliers de données sans rester bloqué dans l'interfaceCette question examine comment restituer les données sans bloquer la page. C'est-à-dire que vous ne pouvez pas restituer des dizaines de milliers d'éléments à la fois, mais devez restituer une partie du DOM à la fois. Vous pouvez ensuite l'actualiser toutes les 16 ms via requestAnimationFrame.
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width, initial-scale=1.0> <meta http-equiv=X-UA -Compatible content=ie=edge> <title>Document</title></head><body> <ul>Contrôle</ul> <script> setTimeout(() => { // Insérez 100 000 éléments de données const total = 100 000 // Insérez 20 éléments à la fois. Si vous pensez que les performances ne sont pas bonnes, réduisez const une fois = 20 // Combien de fois faudra-t-il pour restituer les données const loopCount = total / une fois let countOfRender = 0 let ul = document. querySelector(ul); function add() { // Optimiser les performances, l'insertion ne provoquera pas de reflux const fragment = document.createDocumentFragment(); une fois ; i++) { const li = document.createElement(li); li.innerText = Math.floor(Math.random() * total); 1; boucle(); } function boucle() { if (countOfRender < loopCount) { window.requestAnimationFrame(add); boucle(); }, 0); </script></body></html>compatibilité
Certains anciens navigateurs ne supportent pas cette API. Afin d'utiliser cette API, vous pouvez personnaliser cette méthode et la monter sous la fenêtre :
(function() { var lastTime = 0; var sellers = ['webkit', 'moz']; for(var x = 0; x < sellers.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[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 }; if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) { clearTimeout(id);
Ce qui précède représente l’intégralité du contenu de cet article. J’espère qu’il sera utile à l’étude de chacun. J’espère également que tout le monde soutiendra le réseau VeVb Wulin.