Le guide requestAnimationFrame ()

Apprenez l'API pour effectuer des animations et planifier des événements de manière prévisible

requestAnimationFrame()est une API de navigateur relativement récente. Cela donne un moyen plus prévisible de s'intégrer au cycle de rendu du navigateur.

Il est actuellement pris en charge par tous les navigateurs modernes (et IE 10+)

Browser support

Ce n'est pas une API spécifique aux animations, mais c'est là qu'elle est le plus utilisée.

JavaScript a une boucle d'événements. Il s'exécute en continu pour exécuter JavaScript.

Dans le passé, les animations étaient réalisées en utilisantsetTimeout()ousetInterval(). Vous effectuez une petite animation et vous appelezsetTimeout()pour répéter ce code dans quelques millisecondes à partir de maintenant:

const performAnimation = () => {
  //...
  setTimeout(performAnimation, 1000 / 60)
}
setTimeout(performAnimation, 1000 / 60)

ou

const performAnimation = () => {
  //...
}
setInterval(performAnimation, 1000 / 60)

Vous pouvez arrêter une animation en obtenant le délai d'expiration ou la référence d'intervalle et en l'effaçant:

let timer

const performAnimation = () => { //… timer = setTimeout(performAnimation, 1000 / 60) }

timer = setTimeout(performAnimation, 1000 / 60)

//… clearTimeout(timer)

Le1000 / 60intervalle entre leperformAnimation()Les appels sont déterminés par le taux de rafraîchissement du moniteur, qui est dans la plupart des cas de 60 Hz (60 repeints par seconde), car il est inutile de repeindre si le moniteur ne peut pas l'afficher en raison de ses limitations. Cela nous amène à environ 16,6 ms de temps dont nous disposons pour afficher chaque image.

Le problème avec cette approche est que même si nous spécifions cette précision avec précision, le navigateur pourrait être occupé à effectuer d'autres opérations, et nos appels setTimeout pourraient ne pas arriver à temps pour le repeindre, et il sera retardé au cycle suivant.

C'est mauvais parce que nous perdons une image, et dans la suivante, l'animation est exécutée 2 fois, ce qui fait remarquer à l'œil l'animation maladroite.

Vérifiez cet exemple sur Glitch d'unanimation construite à l'aide de setTimeout ().

requestAnimationFrameest la manière standard d'effectuer des animations, et cela fonctionne d'une manière très différente, bien que le code ressemble beaucoup au code setTimeout / setInterval:

let request

const performAnimation = () => { request = requestAnimationFrame(performAnimation) //animate something }

requestAnimationFrame(performAnimation)

//… cancelAnimationFrame(request) //stop the animation

Cet exemple sur Glitch d'unanimation construite à l'aide de requestAnimationFrame ()montre montre.

Optimisation

requestAnimationFrame()car son introduction était très conviviale pour le processeur, provoquant l'arrêt des animations si la fenêtre ou l'onglet en cours n'est pas visible.

Au moment de l'introduction de requestAnimationFrame (), setTimeout / setInterval s'exécutait même si l'onglet était masqué, mais maintenant que cette approche s'est avérée efficace également pour économiser la batterie, les navigateurs ont également mis en œuvre la limitation pour ces événements, permettant au maximum 1 exécution par seconde .

UtilisantrequestAnimationFramele navigateur peut encore optimiser la consommation des ressources et rendre les animations plus fluides.

Exemples de chronologie

C'est la chronologie parfaite si vous utilisez setTimeout ou setInterval:

Perfect timeline

vous avez un ensemble d'événements de peinture (vert) et de rendu (violet), et votre code est dans la boîte jaune - au fait, ce sont les couleurs utilisées dans les outils de développement du navigateur pour représenter la chronologie:

The devtools timeline

L'illustration montre le cas parfait. Vous avez de la peinture et du rendu toutes les 60 ms, et votre animation se déroule entre les deux, parfaitement régulière.

Si vous avez utilisé un appel de fréquence plus élevée pour votre fonction d'animation:

Too frequent timeline

Remarquez comment, dans chaque image, nous appelons 4 étapes d'animation, avant tout rendu, ce qui rendra l'animation très saccadée.

Que faire si setTimeout ne peut pas s'exécuter à l'heure en raison d'un autre code bloquant la boucle d'événements? Nous nous retrouvons avec une image manquée:

Missed frame

Et si une étape d'animation prend un peu plus que ce que vous prévoyez?

Delay in the timeline

les événements de rendu et de peinture seront également retardés.

C'est ainsirequestAnimationFrame()fonctionne visuellement:

Delay in the timeline

tout le code d'animation s'exécuteavant queles événements de rendu et de peinture. Cela rend le code plus prévisible, et il y a beaucoup de temps pour faire l'animation sans se soucier de dépasser le temps de 16 ms dont nous disposons.

Vérifiercette superbe vidéo de Jake Archibaldsur le sujet.

Téléchargez mon gratuitManuel du débutant JavaScript


Plus de didacticiels sur le navigateur: