Astuce d’animation avec le lissage exponentiel
- Depuis que j’ai commencé à travailler sur des sujets liés à l’animation, j’utilise presque toujours une technique d’animation simple.
- Cette technique est utilisée dans de nombreux contextes : rotation et déplacement de caméra, déplacement de personnages dans des jeux au tour par tour, mouvement d’éléments d’interface, lissage des variations de volume dans une bibliothèque audio, etc.
- Cette technique n’a rien de nouveau, et vous l’avez peut-être déjà entendue ou utilisée, mais je vais en expliquer quelques exemples ainsi que les principes mathématiques.
Bouton bascule
- Lorsqu’on crée un composant d’interface, imaginons par exemple un bouton bascule.
- La position de l’interrupteur du bouton bascule est calculée selon l’état :
max_x s’il est activé, min_x s’il est désactivé.
- Cette méthode fonctionne bien, mais sans animation, elle manque un peu de vie.
- L’animation n’apporte pas seulement un aspect visuel agréable, elle aide aussi l’utilisateur à comprendre ce qui se passe.
- Au lieu de déplacer instantanément l’indicateur du bouton vers sa nouvelle position, on le fait se déplacer en douceur.
- Il faut maintenant mettre à jour l’animation, avec l’inconvénient qu’elle semble se déplacer à vitesse constante.
- On peut y ajouter une fonction d’easing, par exemple
3t^2-2t^3 ou sqrt(t).
- Les différences entre ces fonctions d’easing se voient mieux lorsqu’on lit l’animation au ralenti.
- Désormais, au lieu de simplement mettre à jour la position du switch, il faut suivre l’état de l’animation.
- Avec
sqrt, il faut explicitement utiliser une fonction d’easing différente selon la direction de l’animation.
- La question de savoir ce qui rend le mieux relève des goûts personnels, mais
sqrt me paraît le plus réussi. Le mouvement démarre très vite, puis ralentit bien à l’approche de la destination.
- L’inconvénient de cette version est qu’elle demande une quantité notable de gestion même dans le cas le plus simple, et si l’utilisateur clique au milieu de l’animation, une discontinuité provoque un saut brusque.
Déplacement de caméra
- Imaginons une situation où la carte et la caméra défilent ou se déplacent dans l’espace.
- Ici aussi, il est utile d’ajouter de l’animation.
- Un code d’interpolation à vitesse constante est présenté.
- Le tremblement qui apparaît une fois l’animation terminée vient du fait que
target.x - position.x alterne entre des valeurs positives et négatives.
- Au lieu de
sign(delta), il faut une fonction qui borne le delta.
- Cette méthode est assez compliquée pour quelque chose de simple.
- Quand la vitesse de l’animation dépasse le temps nécessaire à son achèvement, le résultat paraît étrange.
- On pourrait aussi ignorer l’entrée utilisateur tant que l’animation est active, mais cela produit une expérience très frustrante.
- La solution parfaite, bien sûr, c’est le lissage exponentiel.
- Le code change à peine par rapport à l’exemple du bouton bascule.
Fonctionnement interne
- L’article explique ce qu’est
1 - exp(- speed * dt) et comment cela fonctionne.
- On commence par une version simple : rendre la vitesse de déplacement proportionnelle à la distance entre la
position actuelle et la nouvelle position target, afin d’accélérer le mouvement.
- Cette méthode n’a besoin de conserver aucun état autre que la position actuelle et la position cible, et elle s’ajuste automatiquement même si
target change soudainement.
- Il y a toutefois un petit problème : si
speed * dt est supérieur à 1, la position dépasse la cible.
- Pour corriger cela, on peut borner la valeur à 1.
- Si
speed * dt est trop grand, c’est soit parce que la valeur de speed est trop élevée, soit parce que dt est trop grand.
- Dans le cas d’une animation, il serait préférable que tout fonctionne parfaitement dès qu’on applique
dt.
Équation différentielle (oh non)
- Une approche en deux étapes est proposée pour résoudre le problème.
- Le fait que
position += (target - position) * speed * dt fonctionne pour de petits dt mais échoue pour de grands dt est un problème typique des méthodes numériques de résolution des équations différentielles.
- L’article examine ce que résout réellement cette équation.
- Il explique que
position += (target - position) * (1 - exp(- speed * dt)) est la formule correcte pour toutes les valeurs de dt.
Choisir la vitesse
- On pense généralement l’animation en termes de durée.
- Avec la formule exponentielle, l’animation n’est techniquement jamais complètement terminée.
- Le paramètre
speed signifie que 1 / speed est le temps nécessaire pour que position se rapproche de target d’un facteur e = 2.71828....
Lissage exponentiel
- Si l’on cherche « lissage exponentiel », on peut tomber sur une page wiki qui semble totalement sans rapport, mais qui contient en réalité une formule très proche de celle discutée dans ce billet.
- Si
dt est toujours identique et que target change à chaque itération, on peut indexer les valeurs par numéro d’itération et calculer quelque chose comme position[i] = (target[i] - position[i - 1]) * factor.
Titre du dernier paragraphe
- J’avais cette idée de billet depuis plusieurs mois, et je suis heureux de l’avoir enfin terminé.
- Merci d’avoir regardé et lu le journal de développement.
Avis de GN⁺
- Cet article explique la technique du lissage exponentiel utilisée pour rendre les animations plus fluides et plus naturelles. Elle contribue à améliorer l’expérience utilisateur et à rendre les interfaces plus intuitives.
- Le lissage exponentiel peut aussi être utile pour simuler des mouvements physiques, par exemple en développement de jeux pour rendre plus naturels les déplacements de personnages ou de caméra.
- Cette technique est particulièrement efficace quand des éléments d’interface changent d’état et qu’il faut représenter visuellement cette transition. Par exemple, elle permet de rendre le mouvement d’un curseur ou d’un interrupteur plus fluide.
- D’un point de vue critique, le lissage exponentiel peut rendre difficile le contrôle précis de la vitesse et de la durée d’une animation. Cela peut être une limite lorsqu’un designer veut ajuster finement un effet d’animation particulier.
- Parmi les autres bibliothèques ou frameworks offrant des fonctions similaires, on peut citer GreenSock Animation Platform (GSAP) ou anime.js, qui proposent un contrôle plus fin de l’animation avec diverses fonctions d’easing.
- Lorsqu’on adopte la technique du lissage exponentiel, il faut trouver un équilibre entre le naturel de l’animation et la précision du contrôle. Son principal avantage est l’amélioration de l’expérience utilisateur ; son inconvénient est que le réglage fin du timing de l’animation peut devenir plus difficile.
1 commentaires
Commentaires Hacker News
Résumé du premier commentaire :
smoothstep().Résumé du deuxième commentaire :
Résumé du troisième commentaire :
sqrt) serait meilleure qu’une courbe cubique pour un interrupteur à bascule.Résumé du quatrième commentaire :
Résumé du cinquième commentaire :
Résumé du sixième commentaire :
Résumé du septième commentaire :
Résumé du huitième commentaire :
Résumé du neuvième commentaire :
Résumé du dixième commentaire :