In questo periodo stiamo lavorando sempre di più con le animazioni degli SVG.
Ben supportati dai browser moderni, gli SVG permettono di ottenere, con pochi KB di peso, icone, istogrammi, grafici ed altro scalabili nelle varie risoluzioni e visualizzati correttamente nei vari device retina.
Esistono numerose librerie di animazione JavaScript per gli SVG, alcune più complete ed altre pensate per semplificare delle singole funzionalità. Ad esempio possiamo nominare SnapSVG, Vivus, SVGJs e Bonsai.
E poi c’è GreenSock, la nostra scelta per i progetti di TourTools.
GreenSock è una libreria molto performante e completa per le animazioni sul web. Ha una comunità particolarmente attiva alle spalle, un forum seguito costantemente dove si riesce ad avere assistenza in modo veloce ed esaustivo, una buona documentazione ed una serie di plugin molto interessanti, il tutto mantenendo un peso molto ridotto.
Inoltre, poiché è pienamente integrata e supportata da ScrollMagic, con una sola libreria possiamo realizzare le varie animazioni necessarie nelle pagine e le scrollpage richieste nei nostri progetti, senza appesantire il sito con librerie multiple.
Ma, come purtroppo succede per tante tecnologie e risorse sul web, non sempre la documentazione è aggiornata costantemente e quindi si incappa ogni tanto in funzionalità che… non funzionano!
In questo articolo andremo quindi ad analizzare, vedendo un caso reale, come abbiamo sopperito, trovando un'alternativa alla documentazione ufficiale, una di queste funzionalità che non è più correttamente supportata (o meglio, non più supportata dai browser).
Partiamo dall'inizio. La situazione che abbiamo affrontato richiedeva l’animazione dell’icona SVG riportata qui sotto
L’animazione prevede la crescita delle colonne dal basso, quindi la comparsa della linea dell’andamento del grafico da sinistra a destra ed infine l’ingresso della scala con l’uomo sopra.
Cercando soluzioni performanti per animare le barre tramite GreenSock ho trovato la pagina di documentazione di GreenSock relative alle funzionalità di CSS3 dove viene presentata la proprietà clip ed indicando come supporto
Browser support: VERY GOOD (Chrome 2, Safari 1.3, Firefox 1, IE 9, Opera 9.2, iOS 3.2, Android 2.1).
Forte di queste informazioni (Wow, VERY GOOD!!), e trovando la proprietà clip perfetta per il mio caso d’uso, sono andato ad implementare l'animazione.
Innanzitutto, bisogna assicurarsi che gli elementi da animare tramite clip siano in posizione assoluta. Dopodiché si procede con il definire tramite .set nella mia Timeline (o con un Tween apposito se non volete utilizzare Timeline) il clip di partenza che nasconde la barra
.set($("#barra_1"), { clip: "rect(220px, 64px, 220px, 27px)" })
Con questa istruzione vado a creare una clip sulla mia barra che copre del tutto la colonna colorata.
A questo punto con un Tween posso andare a modificare il clip e mostrare cosi la colonna che cresce dal fondo della pagina
.to($("#barra_1"), 0.4, { clip:"rect(90px, 64px, 220px, 27px)", ease: Circ.easeOut })
WOW, comodissimo!! Una riga per settare il clip, una riga per animarlo ed ho ottenuto quello che volevo! Grazie GreenSock!
Bene, riporto la stessa logica alle altre colonne ed alla linea dell’andamento sul grafico ed ottengo l’animazione sottostante
Ora, se state visualizzando questo aritcolo sul browser Firefox non avrete certo problemi nel veder crescere correttamente le barre dell’istogramma e la linea dell’andamento. Se invece siete con Chrome, Safari o Internet Explorer… bè, l’animazione che vi trovate davanti non è proprio meravigliosa, giusto?
Dopo una lunga ricerca, correlata da una bella discussione sul forum, sono riuscito ad individuare e risolvere la problematica.
Lo sviluppo era partito dando per buone le indicazioni di supporto della doc, senza controllare (mea culpa, mea culpa, mea maxima culpa!) se dal 12 dicembre 2012 (data di pubblicazione della pagina nella doc) vi erano state modifiche… E da qui viene tutto il problema!
La proprietà clip è infatti ad oggi deprecata ed il suo supporto molto limitato.
Ok, non disperiamo ed invece rimbocchiamoci le maniche e pensiamo ad una soluzione alternativa.
Potremmo utilizzare clip-path al posto di clip, ma ha ugualmente un basso supporto sui browser. No, non otterremmo nulla.
A questo punto, decidiamo di utilizzare mask ed animare la maschera anziché la clip diretta. Certo, richiede l’animazione di più parametri e la definizione della maschera all’interno dell’SVG, ma è uno standard supportato da tutti i browser, ed è quello che quindi più interessa a noi!
L’utilizzo di mask prevede appunto la definizione delle maschere nella sezione <defs> degli svg. Ad esempio, la maschera per la prima barra avrà la seguente forma
<mask id="b1_mask">
<rect id="barra1_maschera" fill="#FFFFFF" x="27" y="230" width="37" height="0"></rect>
</mask>
Dopodiché la maschera va applicata tramite l’attributo mask. Sempre per la prima barra avremo quindi
<g id="barra_1" mask="url(#b1_mask)">
Bene, le modifiche all’SVG non sono quindi tantissime.
Adesso va però animata la comparsa di questa maschera che, ad ora, ha altezza 0 e coordinata Y 230, quindi appoggiata al fondo del nostro SVG.
Il codice del Tween di GreenSock dovrà pertanto animare due proprietà della maschera allo stesso tempo
- altezza. L’altezza della maschera dovrà essere incrementata fino a far vedere tutta la nostra barra;
- coordinata Y. L’origine della maschera va alzata fino ad arrivare al limite in alto della barra.
Inserendo queste due operazioni nello stesso Tween avremo quindi l’animazione che ci permette di mostrare la barra come se stesse crescendo dal basso
Tween.to($("#barra1_maschera"), 0.4, { attr: { height: 125, y: 95 }, ease: Circ.easeOut })
Applicando la stessa logica anche alle altre 2 barre ed alla linea dell’andamento del grafico otteniamo quindi l’animazione correttamente visibile dai vari browser
Ottimo! Mask è quindi ad oggi (per noi) la soluzione migliore per implementare questo tipo di animazioni.
Il pieno controllo dei vari parametri che nascondono gli elementi permette inoltre di definire funzioni per far comparire il tutto altamente personalizzabile.
Questa è stata solo una brevissima introduzione a mask. Voglio lasciarvi con un bellissimo esempio trovato in rete che sfrutta le maschere
Alla prossima!!!