Web Animations API (WAAPI) c'est quoi ?
Il s'agit d'une nouvelle API JavaScript qui permet de générer du contenu animé et de le contrôler en se basant sur les fonctionnalités de CSS et de SVG. Elle propose des animations puissantes et performantes.
A l'heure actuelle, la prise en charge des navigateurs est assez mince puisque la spécification est en l'état d'ébauche mais le support devrait arriver très vite. Il existe un polyfill si vous souhaitez d'ores et déjà utiliser cette nouvelle API.
L'intérêt de cette API est de pouvoir se passer d'une bibliothèque d'animation embarquée et d'utiliser des fonctions natives au navigateur (donc un peu loupé pour l'instant avec un polyfill, même si celui-ci est très léger).
Ceux qui sont familiers des animations et transitions CSS ne seront pas dépaysés. La seule différence dans la syntaxe en JavaScript est le changement du nom des propriétés de l'animation. Ci-dessous, un tableau comparatif :
Propriétés CSS | Propriétés JavaScript | Description |
---|---|---|
animation-duration |
duration |
durée en millisecondes |
animation-timing-function |
easing |
mêmes valeurs/mots-clé |
animation-delay |
delay |
en millisecondes |
animation-iteration-count |
iterations |
La valeur s'écrit Infinity |
animation-direction |
direction |
mêmes valeurs/mots-clé |
animation-fill-mode |
fill |
mêmes valeurs/mots-clé |
💡 NB : il existe d'autres propriétés JavaScript sans correspondance avec CSS que nous verrons plus bas.
Méthode Element.animate()
Commençons avec un exemple simple :
Le code ci-dessous :
const monElement = document.querySelector('.exemple1').animate({
transform: ['translate3d(0,-100%,0)', 'initial'],
}, {
direction: 'alternate',
duration: 500,
iterations: Infinity,
});
Vous constatez dans cet exemple la présence de la méthode Element.animate()
qui permet de créer l'animation sur un élément (ici sur une classe avec la méthode document.querySelector
). On peut également utiliser la méthode document.getElementById
pour viser un élément unique.
La méthode Element.animate()
doit contenir deux paramètres (ou arguments) obligatoires :
- Les images clés (keyframes).
- La durée (duration).
Contrairement à jQuery , la méthode présente l'avantage d'être intégrée au navigateur, ce qui signifie gain de performance.
Le premier argument de l'élément que nous voulons animer, les images clés, doit être un tableau (array) d'objets. Chaque objet étant une image clé de notre animation.
//tableau d'objets
{
transform: [
'translate3d(0,-100%,0)', 'initial'
]
}
Sachez que par défaut, chaque point de la chronologie est espacé de manière égale. Dans notre exemple, nous avons défini deux points, chacun est donc égal à 50%.
Un autre exemple auquel nous avons ajouté d'autres points :
const monAnimation = [
{
transform: 'translateX(0) rotate(0) scale(1)',
borderRadius: 0
},
{
transform: 'translateX(200px) rotate(1turn) scale(2)',
borderRadius: 0
},
{
transform: 'translateX(400px)',
borderRadius: '50%'
},
{
transform: 'initial',
borderRadius: 'initial'
},
]
const monElement1 = document.querySelector(".exemple2").animate(monAnimation, {
duration: 2000,
iterations: Infinity,
easing: 'ease-in'
});
Il est possible de modifier le timing en utilisant la propriété offset
.
Celle-ci accepte un nombre compris entre 0 et 1 (équivalent aux pourcentages d'une animation CSS. Ex : 0.5 vaut 50%).
Reprenons l'exemple précédent :
Vous pouvez constatez que l'animation est désormais légèrement différente. Le code ci-dessous :
const monElement2 = document.querySelector('.exemple3').animate([
{ transform: 'translateX(0) rotate(0) scale(1)',
borderRadius: 0 },
{ transform: 'translateX(200px) rotate(1turn) scale(2)',
borderRadius: 0,
offset: 0.6 },
{ transform: 'translateX(400px)',
borderRadius: '50%',
offset: 0.8 },
{ transform: 'initial',
borderRadius: 'initial',
offset: 1 }
], {
duration: 2000,
easing: 'ease-in',
iterations: Infinity
});
💡 Jusqu'ici, nous avons utilisé dans nos exemples certaines des options existantes pour les options de synchronisation (EffectTiming), à savoir :
- -
duration
: pour la durée totale de chaque itération de l'animation en millisecondes. La valeur par défaut est 0. - -
iterations
: nombre de fois que l'animation doit se jouer. La valeur par défaut est 1. Peut prendre la valeurInfinity
pour que l'animation se répète indéfiniment (ou tant que l'élément est présent dans le DOM). - -
easing
: indique la manière dont la vitesse varie durant l'animation. Mêmes valeurs/mots-clé et fonctions qu'en CSS. La valeur par défaut pour l'API estlinear
, tandis qu'en CSS, il s'agit deease
.
Voyons les autres options :
delay
: pour retarder le début de l'animation. La valeur par défaut est 0.fill
: applique les styles à la cible avant et après son exécution.endDelay
: le nombre de millisecondes à retarder après la fin d'une animation. Par défaut équivaut à 0.iterationStart
: définit le point dans l'itération où l'animation doit commencer. Il doit s'agir d'un nombre flottant positif (ex :.5).
Un exemple avec retardement de l'animation :
Méthode document.getAnimations()
Nous évoquerons cette méthode très rapidemment, étant donné son manque total de support à l'heure actuelle. Sachez que celle-ci renvoie toujours un tableau de tous les objets d'animations, peu importe le nombre d'animations (une ou plusieurs), incluant les animations et transitions CSS ainsi que les animations web. Il est ainsi possible d'agir directement sur ces animations et d'en changer l'état.
Il existe également d'autres méthodes que nous verrons une fois la spécification plus avancée.
Animation additive
Il existe un paramètre de configuration nommé composite
qui permet de contrôler le comportement d'une animation lorsqu'une autre est active.
Cela permet d'ajouter d'autres animations sur un élément et de les paramètrer indépendamment.
Par exemple, si j'écris ce code :
element.animate({
transform: [transform: 'translateX(0) rotate(0) scale(1)']
}, 1000);
element.animate({
transform: ['translateX(0) rotate(1turn) scale(2)']
}, 2000);
Il en résulte que seule la dernière animation sera jouée. C'est le comportement attendu de la valeur par défaut replace
de la propriété composite
.
Avec la valeur add
, on va pouvoir dissocier et surtout additionner des valeurs sur une animation sur un même élément.
Un exemple avec les deux valeurs évoquées pour vous montrer la différence (💡 à voir sur Chrome ou Firefox Nightly):
Vous pouvez constater que le premier élément ne prend en charge que la dernière animation (la rotation) comme attendu, tandis que le second élément prend en charge les deux transformations (scale
et translate
) de façon distincte avec la valeur add
.
Il existe une dernière valeur pour la propriété composite
, à savoir accumulate
. Similaire à la valeur add
, on notera néanmoins quelques nuances.
En fait, à la différence de la valeur add
, cette valeur va additionner et calculer pour rendre un résultat, ce qui peut changer quelque peu une animation dans le cas des transformations. Suivant l'ordre des valeurs fournies, le calcul peut varier puisque le système de coordonnées va être impacté.
Contrôle des animations
C'est là que les choses commencent à devenir intéressantes. En effet, cette API permet le contrôle des animations grâce à des méthodes :
- -
play()
: pour lire une animation. - -
pause()
: pour interrompre une animation. - -
reverse()
: pour lire une animation à l'envers. - -
cancel()
: pour annuler une animation. - -
playbackRate()
: pour définir la vitesse d'une animation (après la première synchronisation de sa position de lecture). - -
finish()
: pour aller à la fin de l'animation (ou au début si elle est inversée).
Exemple tiré de cet article (EN).
Multiples animations
Tout comme les animations ou transitions CSS, il est bien entendu possible de faire intéragir plusieurs animations en même temps.
Web Animations API ou animations CSS ?
Difficile à dire. Voilà qui devrait répondre à cette question. Plus sérieusement, en général on utilise les animations CSS pour de petites animations non complexes. A contrario, il sera préférable de se tourner vers l'API animations web pour des effets avancés surtout s'ils nécessitent des contrôles.
Si vous vous souciez des performances, vous savez (ou vous vous doutez) probablement que celles-ci peuvent être impactées selon les propriétés que l'on souhaite animer.
Par exemple, la propriété transform
, une fois son état modifié, ne déclenche aucun changement de géométrie ni de repeinture, elle est alors exécutée sur un thread différent du thread principal du navigateur. Il en va de même pour la propriété opacity
.
💡 Je n'ai pas abordé volontairement toutes les notions de cette API, dans la mesure où celle-ci est encore en gestation. Nous y reviendrons quand la spécification sera plus avancée.
Aller plus loin :
Connaître le support d'un navigateur : areweanimatedyet
Série d'articles(EN) sur WAAPI
Galerie de démonstrations
Plus d'informations sur la propriété composite
(EN).
Une autre méthode à découvrir concernant les animations CSS et JavaScript.
Voir aussi CSS Animation Worklet API(EN).
Vous rencontrez un problème avec cet article ?
Vous avez remarqué une faute, un oubli, un lien mort ? Vous ne comprenez pas un point précis de l'article ? Vous pouvez me contacter par mail (contact@guyom-design.com) et je vous aiderai si je le peux. Je ne réponds qu'aux messages respectueux.