• 15 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 2/7/24

Créez des animations plus naturelles avec les fonctions de timing

Tout objet en mouvement doit forcément accélérer, et avant de pouvoir s’arrêter, il doit décélérer.

Une petite balle rebondissante n'a pas la même accélération que le ballon lancé par un joueur de basket, mais tous deux accélèrent. Et c'est cette accélération que notre cerveau va évaluer pour estimer sa masse et l'impulsion donnée, ainsi que son emplacement présent et futur.

Gérez l'accélération et la décélération de vos animations

Pour que nos animations aient l’air réalistes et authentiques, l'accélération et la décélération sont essentielles. Dans le jargon de l’animation, il s'agit du ease-in et du ease-out.

Disons que nous voulons animer une petite boîte pour qu’elle se déplace de 1 000 pixels en 1 000 millisecondes :

Une animation CSS d'un carré qui avance et recule de gauche à droite

Intéressons-nous maintenant à l’accélération et la décélération de notre boîte. Puisqu’il s’agit d’un sujet très visuel, l'utilisation d'une image semble plus pertinente. Essayons donc d’indiquer la vélocité de notre animation sur un graphique :

Graphique représentant la durée et le mouvement d'une animation
Graphique représentant la durée et le mouvement d'une animation

L’axe X représente le pourcentage d’avancement dans la durée de l’animation, et l’axe Y le pourcentage de mouvement effectué. Le graphique commence donc, dans le coin en bas à gauche, avec 0 % de durée écoulée et 0 % de mouvement effectué. Il terminera nécessairement dans le coin supérieur droit, puisque l'animation sera terminée. On peut donc relier ce point de départ et ce point d’arrivée par une ligne qui représente la vélocité de notre animation :

Courbe représentant la vélocité de l'animation

On remarque tout de suite que la vélocité n’est pas une ligne droite, mais que son angle change dès le début lors de l’accélération. Elle change également à la fin pendant la décélération. Dans la première partie, la boîte n’avance pas très vite, donc elle n’avance pas autant sur l’axe mouvement que sur l’axe durée, ce qui aplatit la ligne. À partir de 20 % environ sur l’axe de durée, la boîte atteint une vitesse plus élevée, elle progresse donc plus rapidement et la ligne devient plus pentue.

Quand notre boîte doit freiner pour commencer sa décélération, elle réduit son taux de progression. Le temps progresse plus rapidement que le mouvement, ce qui aplanit de nouveau la courbe. Le graphique nous permet de comprendre rapidement la vitesse de l’animation. Plus la courbe est raide, plus sa vitesse est élevée, et plus elle est plate, plus la vitesse est faible.

Revenons à notre boîte, en gardant notre graphique et son accélération à l'esprit :

Animation d'un carré qui se déplace de gauche à droite

Vous voyez la façon dont elle accélère rapidement, tandis qu’elle ralentit de manière plus progressive ? En CSS, on appelle ces courbes d’accélération des fonctions de timing. On peut utiliser la propriété  transition-timing-function  pour régler la courbe d’accélération d’une transition.

Découvrez les principales fonctions de timing par défaut

La fonction linear

De base, le navigateur nous donne accès à plusieurs courbes d'accélération prédéfinies par défaut dans le CSS.

Intéressons-nous à la première courbe, qui n'en est pas vraiment une : la fonction  linear. Une animation dont le timing est linéaire : elle ne connaît pas d'accentuation à l'accélération ou à la décélération. Sa courbe est totalement droite du point A au point B :

Un graphique d'une fonction linear
Une fonction linear

Pour appliquer une fonction de timing linéaire à l'animation de notre boîte, nous pouvons ajouter la propriété  transition-timing-function  et indiquer sa valeur en  linear  :

transition: transform 1000ms;
transition-timing-function: linear;

Ou bien nous pouvons l’ajouter au raccourci de la propriété de transition, en précisant le mot clé  linear  dans les valeurs :

transition: transform 1000ms linear;

Si on revient à notre boîte en mouvement avec sa courbe d’accélération linéaire, on pourra constater qu’elle se déplace à vitesse constante du départ à l’arrivée :

Une animation CSS d'un carré qui avance et recule de gauche à droite avec une fonction linear
Fonction linear

Les fonctions ease-in-out, ease-in et ease-out

La seconde fonction que j'aimerais vous faire découvrir est  ease-in-out. C’est la fonction de timing préférée de beaucoup d’animateurs car elle suit une courbe d’accélération et de décélérationsubtile, comme vous pouvez le voir sur le graphique suivant :

Graphique de la fonction ease-in-out
Graphique de la fonction ease-in-out

Essayons-la maintenant dans la transition de notre boîte :

transition: transform 1000ms ease-in-out;

Voilà ce que ça donne :

Une animation CSS d'un carré qui avance et recule de gauche à droite avec une fonction ease-in-out
Fonction ease-in-out

On peut voir l’augmentation de la vitesse puis sa réduction, mais ses accélérations et décélérations sont suffisamment subtiles pour se fondre dans le mouvement. Ça tombe bien, on cherche justement à créer un mouvement naturel !

On peut aussi choisir de seulement d'accentuer l'accélération ou la décélération avec   ease-in  et   ease-out.

// Fonction de timing ease-in :
transition: transform 1000ms ease-in;
// Fonction de timing ease-out :
transition: transform 1000ms ease-out;

Si on compare leurs courbes au graphique  ease-in-out, on constate que le graphique  ease-in  correspond au début du  ease-in-out, avec une fin linéaire. Et inversement, le départ de   ease-out  est linéaire, alors que sa courbe de décélération s'accentue comme celle de  ease-in-out  :

Graphique des fonctions ease in, ease out et ease in-out
Graphique des fonctions ease-in, ease-out et ease in-out

En les observant bien, on peut voir que  ease-in  est plus lent au départ, tandis que  ease-out  freine plus tôt :

Deux animations CSS d'un carré qui avance et recule de gauche à droite avec les fonctions ease-in et ease-out
Fonctions ease-in et ease-out

Notre perception du mouvement selon l'accélération et le ralentissement devient évidente si on regarde les deux fonctions côte à côte : elles ont toutes les deux exactement la même durée, mais en raison de leurs différentes fonctions de timing, le mouvement et même la durée semblent totalement différents.

La fonction ease

Alors quel timing s’applique aux transitions que nous avons réalisées jusqu’ici ? Eh bien, lorsqu'aucune n'est précisée, le navigateur applique la fonction ease par défaut, qui ressemble aux courbes que nous venons de décrire. Mais  ease  suit un profil d’accélération plus net, et une rampe de décélération plus prononcée :

Graphique de la fonction ease
Graphique de la fonction ease

Si la courbe  ease  vous paraît familière, c’est normal ! C’est la courbe que notre boîte suivait au début de ce chapitre. Vous pouvez la comparer aux autres fonctions de timing par défaut des navigateurs :

Animations d'un carré qui avance et recule de gauche à droite avec différentes fonctions

Allez à votre propre rythme avec la fonction cubic-bezier

Les fonctions de timing intégrées à CSS nous permettent d'ajouter du naturel à nos animations très simplement, mais vous pouvez avoir envie de créer vos propres effets de timing.

Reprenons l'exercice avec nos boules grossissantes, pour en faire un compteur “force-mètre” (oui oui, ce jeu où je ne gagne jamais dans les fêtes foraines) :

Une animation CSS d'un forcemètre

Quand on maintient le clic appuyé sur le bouton, la boule monte au sommet du compteur. Ça fonctionne bien, si ce n’est le fait qu’on ne ressent aucune tension, aucun suspense. On ne doute pas un seul instant que la boule va atteindre le sommet, l’utilisateur ne se sentira donc pas engagé dans son interaction.

Un utilisateur qui s'en fiche ? Ça ne va pas du tout ça ! Modifions donc l'accélération de la boule pour apporter un élément de doute. Pour l’instant, la transition est fixée à la valeur de la fonction de timing par défaut  ease  :

$trans-dur: 2000ms;
transform: translateY(100%);
transition: transform $trans-dur;

ease  comprend un  ease-in  léger puis un   ease-out  un peu plus marqué. Mais si on faisait monter la boule comme une fusée au départ, pour la faire ralentir de plus en plus à l’approche du sommet, ça changerait le ressenti. Les utilisateurs se sentiraient impliqués, comme s'ils avaient eux-mêmes utilisé un marteau pour faire monter la boule : ils s'appliqueraient davantage sur le clic de leur souris.

Sur un graphique, voilà la courbe de l'effet qu'on cherche à obtenir :

Graphique du mouvement que l'on cherche à reproduire
La représentation graphique du mouvement recherché

Cette courbe ne ressemble à aucune des configurations que nous avons vues… Pour que notre boule la suive, nous allons donc devoir la créer nous-mêmes.

Pour cela, je vous présente la fonction CSS cubic-bezier.

Il faut savoir que les fonctions de timing intégrées à CSS que nous avons vues jusqu'à présent ne sont que des raccourcis de fonctions cubic-bezier.

La fonction  cubic-bezier  fonctionne comme la fonction  rgb()  : on indique une liste de valeurs numériques, mais au lieu de transformer ces chiffres en couleur, la fonction  cubic-bezier  les transforme en courbe d’accélération. Par exemple,   ease-in-out  peut être écrite ainsi :

.selector {
    transition-timing-function: cubic-bezier(.42, 0, .58, 1);
}

Super, mais… comment est-ce qu’on transforme la courbe d’accélération de notre effet en fonction  cubic-bezier() ?

cubic-bezier()  a besoin d’une liste de quatre nombres, qui sont les coordonnées de deux points sur le graphique. Les deux premiers nombres sont les coordonnées X et Y du point qui déterminent le  ease-in  de la courbe d’accélération, et les deux suivants déterminent le  ease-out  :

.selector {
/*(X1,Y1)(X2,Y2)*/
    transition-timing-function: cubic-bezier(.42, 0, .58, 1);
}

Maintenant, imaginez que la courbe d’accélération soit une corde tendue entre deux arbres. Si on attrapait cette corde à deux points différents, et qu’on poussait dans deux directions différentes, on forcerait la corde à dévier de sa ligne, dans ces deux directions. Les coordonnées que nous indiquons dans  cubic-bezier()  représentent la force et la direction dans laquelle nous voulons faire dévier la ligne de notre courbe d’accélération.

Plaçons les coordonnées de notre  ease-in-out  sur le graphique et voyons comment elles créent une courbe d’accélération :

La courbe d'accélération

Superbe ! Mais… comment est-ce qu’on transforme ça :

La courbe de bézier que l'on cherche à atteindre
La courbe de bézier que l'on cherche à atteindre

pour obtenir les coordonnées cubic-bezier (0, .75, .08, 1) ???

On pourrait deviner les coordonnées à l'aveuglette… ou bien utiliser un outil en ligne pour nous aider, comme le bien nommé cubic-bezier.com.

Sur ce site, vous êtes accueilli sur la gauche par le graphique d’une courbe par défaut, accompagnée de deux leviers que vous pouvez déplacer pour modifier le profil de l’accélération :

Modification de la courbe avec un site internet

 Vous pouvez voir les valeurs de la fonction cubic-bezier changer quand vous déplacez les leviers. Pour créer notre courbe personnalisée, nous pouvons faire glisser les leviers  ease-in  et  ease-out  de manière à créer la courbe que nous voulons obtenir, puis utiliser dans notre code les valeurs cubic-bezier générées par le site.

Voici la courbe pour notre force-mètre :

Image de la courbe pour le force-mètre

Il ne nous reste plus qu’à coller ces valeurs cubic-bezier() dans notre transition, et c’est parti !

$trans-dur: 2000ms;
.strength {
    transform: translateY(100%);
    transition: transform $trans-dur cubic-bezier(0, .75, .08, 1);
}

Notre transition crée enfin un peu d'enjeu ! La boule accélère très rapidement, mais traîne sur la fin :

Une animation CSS du force-mètre amélioré

Comme nous l'avons vu ici, les effets de timing ne sont pas uniquement fonctionnels pour donner un côté naturel à nos animations, mais ils peuvent également parfois transmettre une véritable émotion et raconter une histoire.

Les configurations par défaut peuvent souvent suffire, mais parfois, il est nécessaire de créer une courbe personnalisée pour aboutir à l’effet souhaité.

En résumé

  • l’accélération et la décélération des transitions sont contrôlées par la propriété  transition-timing-function ;

  • si aucune fonction de timing n’est indiquée, la transition utilisera la fonction  ease. Elle suit un profil d’accélération plus net, et une rampe de décélération plus prononcée ;

  • parmi les autres mots clés pour les fonctions de temporisation, on peut trouver  ease-in,   ease-out,   ease-in-out, et  linear ;

  • quand aucune fonction de timing par défaut ne correspond à l’animation, il est possible de créer ses propres courbes d’animation personnalisée à l’aide de la fonction  cubic-bezier()  ;

  • il existe des outils pour ajuster les effets de timing avec la fonction  cubic-bezier()  .

Félicitation, vous avez terminé cette première partie !  Apprenez dans la seconde partie de ce cours à maîtriser les translations, les rotations et l’opacité.

Example of certificate of achievement
Example of certificate of achievement