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 :
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 :
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 :
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 :
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 :
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 :
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 :
Essayons-la maintenant dans la transition de notre boîte :
transition: transform 1000ms ease-in-out;
Voilà ce que ça donne :
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
:
En les observant bien, on peut voir que ease-in
est plus lent au départ, tandis que ease-out
freine plus tôt :
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 :
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 :
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) :
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 :
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 :
Superbe ! Mais… comment est-ce qu’on transforme ça :
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 :
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 :
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 :
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
, etlinear
;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é.