Animazioni web: element.animate() è ora disponibile in Chrome 36

Brendan Kenny
Brendan Kenny

L'animazione sul Web un tempo era di competenza di JavaScript, ma con il passaggio del mondo ai dispositivi mobili, le animazioni sono state spostate in CSS per la sintassi dichiarativa e le ottimizzazioni che i browser sono stati in grado di realizzare. Con i 60 FPS sui dispositivi mobili il tuo obiettivo è sempre quello di cui hai bisogno, non devi mai uscire da ciò che i browser sanno come mostrare in modo efficiente.

Stiamo apparendo un numero maggiore di strumenti per rendere più efficienti le animazioni basate su JavaScript, ma il Santo Graal è un'unificazione di animazioni dichiarative e imperative , in cui la decisione su come scrivere le animazioni si basa su qual è il codice più chiaro, non su ciò che è possibile in una forma e non nell'altra.

Le animazioni web rispondono a questa chiamata e la prima parte è arrivata in Chrome 36 nel formato element.animate(). Questa nuova funzione ti consente di creare un'animazione esclusivamente in JavaScript e di eseguirla con la stessa efficienza di qualsiasi animazione o transizione CSS (infatti, a partire da Chrome 34, lo stesso motore delle animazioni web supporta tutti questi metodi).

La sintassi è semplice e le sue parti dovrebbero esserti familiari se hai mai scritto una transizione o un'animazione CSS:

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

Il più grande vantaggio di questa nuova funzione è l'eliminazione di molti passaggi imbarazzanti che in precedenza dovevamo saltare per ottenere un'animazione fluida e senza interruzioni.

Ad esempio, per l'anno scorso Segui Babbo Natale volevamo che la neve cadesse continuamente, abbiamo deciso di animarla tramite CSS in modo che potesse essere eseguita in modo molto efficiente.

Tuttavia, volevamo scegliere la posizione orizzontale della neve in modo dinamico in base allo schermo e agli eventi che si verificavano nella scena stessa e, naturalmente, l'altezza della neve che cadeva (l'altezza della finestra del browser dell'utente) non sarebbe stata nota fino a quando non eravamo in esecuzione. Questo significava davvero dover utilizzare le transizioni CSS, poiché la creazione di un'animazione CSS in fase di esecuzione diventa rapidamente complessa (e centinaia di fiocchi di neve significano centinaia di nuove regole di stile).

Abbiamo quindi adottato il seguente approccio, che dovrebbe esserti familiare:

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 chiave si trova nel commento "Attendi un frame". Per avviare correttamente una transizione, il browser deve confermare che l'elemento è nella posizione iniziale. Esistono diversi modi per farlo. Uno dei modi più comuni è leggere da una delle proprietà dell'elemento che obbliga il browser a calcolare il layout, assicurandosi così di sapere che l'elemento ha una posizione iniziale prima di passare alla posizione finale. L'utilizzo di questo metodo ti consente di congratularti con te stesso per la tua superiore conoscenza degli elementi interni del browser e al contempo di sentirti "sporco" a ogni pressione di un tasto.

Al contrario, la chiamata element.animate() equivalente non potrebbe essere più chiara, in quanto indica esattamente il significato:

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

Ci sono molte altre opzioni. Proprio come con le controparti CSS, le animazioni web possono essere ritardate e iterate:

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

AnimationPlayer

element.animate() restituisce in realtà un oggetto AnimationPlayer, che diventerà sempre più importante con il lancio di ulteriori specifiche delle animazioni web. Alle animazioni create tramite JavaScript e CSS sarà associato un AnimationPlayer, che potrà essere combinato perfettamente in modi utili e interessanti.

Per ora, però, AnimationPlayer ha soltanto due funzionalità, entrambe molto utili. Puoi annullare un'animazione in qualsiasi momento utilizzando 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();

Inoltre, con sollievo di chiunque abbia tentato di creare un sistema di animazione basato sulle animazioni o sulle transizioni CSS in passato, le animazioni web attivano sempre un evento una volta terminate:

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!');
}

Prova

Tutto questo sarà disponibile in Chrome 36, passando oggi alla versione beta. Se vuoi provarla, prova a utilizzare l'implementazione nativa in Chrome 36. Tuttavia, esiste un polyfill delle animazioni web, che introduce una parte significativamente più ampia della specifica completa delle animazioni web in tutti i browser moderni e evergreen.

È disponibile una demo dell'effetto neve che puoi provare a utilizzare sia la versione nativa di element.animate() sia il polyfill.

Facci sapere la tua opinione

Tuttavia, questa è un'anteprima delle novità in arrivo e viene rilasciata appositamente per ricevere subito feedback dagli sviluppatori. Non siamo ancora sicuri di aver accolto tutti i casi d'uso o di aver tagliato via ogni limite delle attuali API per l'animazione. L'unico modo che ci consente di saperlo e di agire nel modo giusto è che gli sviluppatori lo provino e ci comunichino la loro opinione.

I commenti su questo post sono ovviamente preziosi e i commenti sullo standard possono essere inviati ai gruppi di lavoro CSS e SVG tramite la mailing list Public-fx.

Aggiornamento, ottobre 2014: in Chrome 39 viene aggiunto il supporto di diversi metodi aggiuntivi relativi al controllo della riproduzione, ad esempio play(), pause() e reverse(). Inoltre, supporta il passaggio a un punto specifico nella sequenza temporale di un'animazione tramite la proprietà currentTime. Puoi vedere questa funzionalità in azione in questa nuova demo.

Grazie a Addy Osmani e Max Heinritz per l'assistenza per questo post.