Commande de lecture des animations Web dans Chrome 39

Plus tôt cette année, Chrome 36 a intégré la méthode "element.animate" dans le cadre de la spécification Web Animations. Elle permet d'utiliser des animations natives efficaces et écrites de manière impérative, ce qui permet aux développeurs de créer leurs animations et transitions avec l'approche qui leur convient le mieux.

Pour vous rafraîchir la mémoire, voici comment vous pouvez animer un nuage à l'écran, avec un rappel une fois l'opération terminée:

var player = cloud.animate([
    {transform: 'translateX(' + start + 'px)'},
    {transform: 'translateX(' + end + 'px)'}
], 5000);
player.onfinish = function() {
    console.info('Cloud moved across the screen!');
    startRaining(cloud);
};

Cette approche est incroyablement simple et peut s'avérer utile si vous créez des animations ou des transitions de manière impérative. Toutefois, dans Chrome 39, des fonctionnalités de commande de lecture ont été ajoutées à l'objet AnimationPlayer renvoyé par element.animate. Auparavant, une fois qu'une animation était créée, vous ne pouviez appeler que cancel() ou écouter l'événement de fin.

Ces ajouts de lecture ouvrent les possibilités de ce que les animations Web peuvent faire : transformer les animations en un outil généraliste, plutôt que d'être normatifs sur les transitions, c'est-à-dire des animations "fixes" ou prédéfinies.

Mettre en pause, revenir en arrière ou modifier la vitesse de lecture

Commençons par mettre à jour l'exemple ci-dessus pour mettre en pause l'animation si l'utilisateur clique sur le nuage:

cloud.addEventListener('mousedown', function() {
    player.pause();
});

Vous pouvez également modifier la propriété playbackRate:

function changeWindSpeed() {
    player.playbackRate *= (Math.random() * 2.0);
}

Vous pouvez également appeler la méthode reverse(), ce qui revient normalement à inverser la valeur playbackRate actuelle (multipliée par -1). Il existe toutefois quelques cas particuliers:

  • Si la modification causée par la méthode reverse() entraîne la fin effective de l'animation en cours, currentTime est également inversé.Par exemple, si une toute nouvelle animation est inversée, toute l'animation est lue à l'envers.

  • Si le lecteur est en pause, la lecture de l'animation commence.

Utiliser la barre de lecture du lecteur

Un AnimationPlayer permet désormais de modifier son currentTime pendant l'exécution d'une animation. Normalement, cette valeur augmente au fil du temps (ou diminue, si la valeur playbackRate est négative). Cela peut permettre de contrôler la position d'une animation en externe, éventuellement par le biais d'une interaction de l'utilisateur. Ceci est communément appelé frottement.

Par exemple, si votre page HTML représente le ciel et que vous souhaitez faire glisser un doigt pour déplacer un nuage en cours de lecture, vous pouvez ajouter des gestionnaires au document:

var startEvent, startEventTime;
document.addEventListener('touchstart', function(event) {
    startEvent = event;
    startEventTime = players.currentTime;
    player.pause();
});
document.addEventListener('touchmove', function(event) {
    if (!startEvent) return;
    var delta = startEvent.touches[0].screenX -
        event.changedTouches[0].screenX;
    player.currentTime = startEventTime + delta;
});

Lorsque vous faites glisser le curseur sur le document, la currentTime est modifiée pour refléter la distance par rapport à l'événement d'origine. Vous pouvez également reprendre la lecture de l'animation à la fin du geste:

document.addEventListener('touchend', function(event) {
    startEvent = null;
    player.play();
});

Cette technique peut même être combinée avec un comportement d'inversion, selon l'endroit où le curseur a été soulevé sur la page (démonstration combinée).

Au lieu de balayer un AnimationPlayer en réponse à une interaction de l'utilisateur, son currentTime peut également être utilisé pour afficher la progression ou l'état (par exemple, l'état d'un téléchargement).

Ici, l'utilitaire est qu'un AnimationPlayer permet de définir une valeur et de laisser l'implémentation native sous-jacente se charger de la visualisation de la progression. Dans le cas d'un téléchargement, la durée d'une animation peut être définie sur la taille de téléchargement totale, et currentTime sur la taille actuellement téléchargée (démo).

Transitions et gestes dans l'interface utilisateur

Les plates-formes mobiles sont depuis longtemps l'univers des gestes courants: glisser-déposer, glissement, glissement d'un geste vif, etc. Ces gestes ont tendance à avoir un thème commun: un composant d'interface utilisateur déplaçable, tel que le « tirer pour actualiser » dans une liste ou une barre latérale ouverte à partir du côté gauche de l'écran.

Avec les animations Web, un effet similaire est très facile à reproduire ici sur le Web - sur ordinateur de bureau ou sur mobile. Par exemple, lorsqu'un geste contrôlant currentTime se termine:

var steps = [ /* animation steps */ ];
var duration = 1000;
var player = target.animate(steps, duration);
player.pause();
configureStartMoveListeners(player);

var setpoints = [0, 500, 1000];
document.addEventListener('touchend', function(event) {
    var srcTime = player.currentTime;
    var dstTime = findNearest(setpoints, srcTime);
    var driftDuration = dstTime - srcTime;

    if (!driftDuration) {
    runCallback(dstTime);
    return;
    }

    var driftPlayer = target.animate(steps, {
    duration: duration,
    iterationStart: Math.min(srcTime, dstTime) / duration,
    iterations: Math.abs(driftDuration) / duration,
    playbackRate: Math.sign(driftDuration)
    });
    driftPlayer.onfinish = function() { runCallback(dstTime); };
    player.currentTime = dstTime;
});

Cela crée une animation supplémentaire qui effectue une "dérive". Cela va de l'endroit où le geste a été effectué jusqu'à notre cible correcte connue.

La priorité des animations dépend de leur ordre de création: dans ce cas, driftPlayer est prioritaire sur le lecteur. Une fois l'opération driftPlayer terminée, elle et ses effets disparaissent. Cependant, l'heure finale correspondra à la valeur currentTime du joueur sous-jacent, afin que votre interface utilisateur reste cohérente.

Enfin, si vous aimez les chatons, vous pouvez utiliser l'application Web de démonstration pour montrer ces gestes. Il est adapté aux mobiles et utilise le polyfill pour assurer la rétrocompatibilité. Essayez donc de le charger sur votre appareil mobile.

Aller et élément.animate

La méthode element.animate fonctionne actuellement, que vous l'utilisiez pour des animations simples ou pour exploiter son AnimationPlayer renvoyé d'une autre manière.

Ces deux fonctionnalités sont également entièrement compatibles avec d'autres navigateurs modernes via un polyfill léger. Ce polyfill effectue également la détection de caractéristiques. Ainsi, à mesure que les fournisseurs de navigateurs implémentent la spécification, cette fonctionnalité s'améliore au fil du temps.

La spécification Web Animations va également continuer à évoluer. Si vous souhaitez découvrir les fonctionnalités à venir, elles sont également disponibles dans un polyfill plus détaillé: web-animations-next.