Animations Web : item.animate() est désormais disponible dans Chrome 36

Brendan Kenny
Brendan Kenny

L'animation sur le Web était autrefois l'apanage de JavaScript, mais à mesure que le monde est passé au mobile, les animations ont été transférées vers le CSS en raison de la syntaxe déclarative et des optimisations que les navigateurs pouvaient effectuer avec celui-ci. Étant donné que votre objectif est toujours d'atteindre 60 FPS sur mobile, il est logique de ne jamais dépasser ce que les navigateurs savent afficher efficacement.

De plus en plus d'outils apparaissent pour rendre les animations JavaScript plus efficaces, mais l'objectif ultime est d'unifier les animations déclaratives et impératives , où la décision d'écrire vos animations est basée sur le code le plus clair, et non sur ce qui est possible dans une forme et pas dans l'autre.

Les animations Web sont là pour répondre à cet appel. La première partie est disponible dans Chrome 36 sous la forme de element.animate(). Cette nouvelle fonction vous permet de créer une animation entièrement en JavaScript et de l'exécuter aussi efficacement que n'importe quelle animation ou transition CSS (en fait, depuis Chrome 34, le même moteur Web Animations gère toutes ces méthodes).

La syntaxe est simple, et ses éléments devraient vous être familiers si vous avez déjà écrit une transition ou une animation CSS:

element.animate([
    {cssProperty: value0},
    {cssProperty: value1},
    {cssProperty: value2},
    //...
], {
    duration: timeInMs,
    iterations: iterationCount,
    delay: delayValue
});

Le plus grand avantage de cette nouvelle fonction est qu'elle élimine de nombreuses étapes complexes que nous devions auparavant suivre pour obtenir une animation fluide et sans à-coups.

Par exemple, pour le Santa Tracker de l'année dernière, nous voulions que la neige tombe en continu. Nous avons donc décidé de l'animer via CSS pour l'exécuter de manière efficace.

Toutefois, nous voulions choisir la position horizontale de la neige de manière dynamique en fonction de l'écran et des événements qui se déroulent dans la scène elle-même. Bien entendu, la hauteur de la chute de neige (la hauteur de la fenêtre du navigateur de l'utilisateur) ne serait connue qu'au moment de l'exécution. Nous avons donc dû utiliser des transitions CSS, car la création d'une animation CSS au moment de l'exécution devient rapidement complexe (et des centaines de flocons de neige signifient des centaines de nouvelles règles de style).

Nous avons donc suivi l'approche suivante, qui devrait vous être familière:

snowFlake.style.transform = 'translate(' + snowLeft + 'px, -100%)';
// wait a frame
snowFlake.offsetWidth;
snowFlake.style.transitionProperty = 'transform';
snowFlake.style.transitionDuration = '1500ms';
snowFlake.style.transform = 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)';

La clé se trouve dans le commentaire "attendre un frame". Pour qu'une transition puisse être lancée, le navigateur doit confirmer que l'élément se trouve dans la position de départ. Pour ce faire, vous disposez de plusieurs méthodes. L'une des méthodes les plus courantes consiste à lire l'une des propriétés de l'élément qui oblige le navigateur à calculer la mise en page, ce qui garantit qu'il sait que l'élément a une position de départ avant de passer à la position finale. Cette méthode vous permet de vous féliciter de votre connaissance supérieure des composants internes du navigateur, tout en vous sentant sale à chaque frappe.

En revanche, l'appel element.animate() équivalent ne pourrait pas être plus clair, indiquant exactement ce qui est prévu:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);

Il existe de nombreuses autres options. Tout comme leurs homologues CSS, les animations Web peuvent être retardées et itérées:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], {
    duration: 1500,
    iterations: 10,
    delay: 300
});

AnimationPlayer

element.animate() renvoie en fait un objet AnimationPlayer, qui deviendra de plus en plus important à mesure que la spécification Web Animations sera lancée. Les animations créées en JavaScript et en CSS sont associées à des AnimationPlayers, ce qui permet de les combiner facilement de manière utile et intéressante.

Pour le moment, AnimationPlayer ne propose que deux fonctionnalités, toutes deux très utiles. Vous pouvez annuler une animation à tout moment à l'aide de AnimationPlayer.cancel():

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// less than 1500ms later...changed my mind
player.cancel();

Et, pour le soulagement de tous ceux qui ont déjà essayé de créer un système d'animation autour d'animations ou de transitions CSS, les animations Web déclenchent toujours un événement à la fin:

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
player.onfinish = function(e) {
    console.log('per aspera ad terra!');
}

Essayer

Tout cela est disponible dans Chrome 36, qui passe en version bêta aujourd'hui. Si vous souhaitez essayer, utilisez l'implémentation native dans Chrome 36. Toutefois, il existe un polyfill Web Animations, qui apporte une partie beaucoup plus importante de la spécification Web Animations complète à tous les navigateurs modernes et pérennes.

Une démonstration de l'effet de neige est disponible pour vous permettre d'essayer à la fois la version native de element.animate() et le polyfill.

Donnez-nous votre avis

Il s'agit en fait d'un aperçu de ce qui vous attend, et il est publié spécifiquement pour recueillir les commentaires des développeurs dès maintenant. Nous ne sommes pas encore sûrs d'avoir couvert tous les cas d'utilisation ni d'avoir corrigé tous les problèmes des API actuelles pour l'animation. La seule façon pour nous de savoir si nous avons bien fait est que les développeurs l'essaient et nous disent ce qu'ils en pensent.

Les commentaires sur ce post sont bien sûr les bienvenus. Vous pouvez également envoyer vos commentaires sur la norme elle-même aux groupes de travail CSS et SVG via la liste de diffusion public-fx.

Mise à jour d'octobre 2014: Chrome 39 prend en charge plusieurs autres modes de contrôle de la lecture, tels que play(), pause() et reverse(). Il permet également de sauter à un point spécifique de la timeline d'une animation via la propriété currentTime. Pour voir cette fonctionnalité en action, consultez cette nouvelle démonstration.

Merci à Addy Osmani et Max Heinritz pour leur aide dans la rédaction de cet article.