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

Brendan Kenny
Brendan Kenny

L'animation sur le Web était autrefois le domaine de JavaScript, mais à mesure que le monde s'est tourné vers le mobile, les animations se sont déplacées vers le CSS en raison de la syntaxe déclarative et des optimisations que les navigateurs ont pu apporter. La fréquence d'images de 60 FPS sur mobile est toujours votre objectif. Vous avez donc tout intérêt à ne jamais sortir de ce que les navigateurs savent afficher de façon efficace.

De plus en plus d'outils semblent rendre les animations basées sur JavaScript plus efficaces, mais le point fort est l'unification des animations déclaratives et impératives : la décision d'écrire vos animations repose sur le code le plus clair, et non sur ce qui est possible sous une forme et pas dans une autre.

Les animations Web permettent de répondre à cet appel, et la première partie a été intégrée à Chrome 36 sous la forme element.animate(). Cette nouvelle fonction vous permet de créer une animation uniquement en JavaScript et de l'exécuter aussi efficacement que n'importe quelle animation ou transition CSS. En fait, à partir de Chrome 34, le même moteur d'animations Web gère toutes ces méthodes.

Si vous avez déjà écrit une transition ou une animation CSS, la syntaxe est simple et vous devez connaître les différentes parties qui la composent:

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

Le principal avantage de cette nouvelle fonction est l'élimination d'un grand nombre d'obstacles gênants que nous devions auparavant effectuer pour obtenir une animation fluide et sans à-coups.

Par exemple, l'année dernière, l'application Sur la piste du père Noël voulait que la neige tombe en continu. Nous avons donc décidé de l'animer avec le CSS pour que cela soit efficace.

Cependant, 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 que lorsque l'exécution était en cours. Nous devions donc vraiment 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 impliquent des centaines de nouvelles règles de style).

Nous avons donc adopté 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)';

L'élément clé se trouve dans ce commentaire "wait a frame". Pour lancer une transition, le navigateur doit confirmer que l'élément se trouve en position de départ. Il y a plusieurs façons de le faire. L'une des méthodes les plus courantes consiste à lire à partir de l'une des propriétés de l'élément. Cela oblige le navigateur à calculer la mise en page, ce qui lui permet de savoir que l'élément a une position de départ avant de passer à la position de fin. Cette méthode vous permet de vous féliciter de vos meilleures connaissances sur les composants internes du navigateur, tout en vous sentant sale à chaque frappe.

En revanche, l'appel element.animate() équivalent n'a pas pu être plus clair, car il décrit 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 avec ses équivalents CSS, les animations Web peuvent être différé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 des spécifications Web Animations seront plus nombreuses. Les animations JavaScript et CSS sont associées à des AnimationPlayers, ce qui permet de les combiner facilement de manière utile et intéressante.

Pour l'instant, cependant, AnimationPlayer ne dispose que de 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();

Par ailleurs, afin de soulager tous ceux qui ont déjà essayé de créer un système d'animation à partir d'animations ou de transitions CSS par le passé, les animations Web déclenchent systématiquement un événement lorsqu'elles sont terminées:

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

Toutes ces fonctionnalités sont disponibles dans Chrome 36, et nous passerons en version bêta dès aujourd'hui. Si vous souhaitez l'essayer, essayez d'utiliser l'implémentation native dans Chrome 36. Toutefois, il existe un polyfill Web Animations, qui permet d'utiliser une plus grande partie de la spécification Web Animations complète dans tous les navigateurs modernes et intemporels.

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

Donnez-nous votre avis

En réalité, il ne s'agit que d'un aperçu de ce qui vous attend. Il est publié spécifiquement pour recueillir immédiatement l'avis des développeurs. Nous ne savons pas encore si nous avons répondu à tous les cas d'utilisation ou si nous avons nettoyé toutes les extrémités des API actuelles pour l'animation. La seule façon pour nous de le savoir et de bien faire les choses est que les développeurs l'essaient et nous donnent leur avis.

Les commentaires sur cet article sont bien sûr utiles. Vous pouvez adresser 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 est compatible avec plusieurs autres méthodes de contrôle de la lecture, telles que play(), pause() et reverse(). Elle permet également de passer à un point spécifique de la timeline d'une animation via la propriété currentTime. Vous pouvez observer son fonctionnement dans cette nouvelle démonstration.

Merci à Addy Osmani et Max Heinritz pour leur aide sur ce post.