Evitare di verniciare è fondamentale per ottenere una frequenza fotogrammi liscia e omogenea, soprattutto sui dispositivi mobili. A volte, tuttavia, le vernici affiorano nei luoghi più insoliti. Questo articolo spiega perché le GIF animate possono causare colori inutili e la semplice soluzione che puoi applicare.
Livelli di bellezza
Come probabilmente saprai, i browser moderni possono colorare gruppi di elementi DOM in "immagini" separate, chiamate livelli. A volte c'è un solo livello per l'intera pagina, altre centinaia o, in rari casi, migliaia.
Quando gli elementi DOM vengono raggruppati in un livello e uno degli elementi cambia visivamente, si finisce per colorare non solo l'elemento modificato, ma anche tutti gli altri elementi del livello che si sovrappongono a quello modificato. Dipingere un elemento sopra un altro comporta che i pixel sovrascritti vengono "persi" per sempre; se vuoi recuperare i pixel originali, devi ricolorarli.
A volte, quindi, vogliamo isolare un elemento dagli altri in modo che, una volta dipinto, non sia necessario ridipingere gli altri elementi che non sono cambiati. Ad esempio, se combini un'intestazione di pagina fissa con contenuti scorrevoli, devi ricolorare l'intestazione ogni volta che i contenuti scorrono, nonché i contenuti appena visibili. Posizionando l'intestazione in un livello separato, il browser può ottimizzare lo scorrimento. Quando scorri, il browser può spostare i livelli, probabilmente con l'aiuto della GPU, ed evitare di dipingere entrambi i livelli.
Ogni livello aggiuntivo aumenta il consumo di memoria e aumenta l'overhead in termini di prestazioni, quindi l'obiettivo è raggruppare la pagina nel minor numero possibile di livelli mantenendo buone prestazioni.
Cosa c'entra tutto questo con le GIF animate?
Diamo un'occhiata a questa immagine:
Questa è una potenziale configurazione di livello per una semplice app. Sono presenti quattro livelli: tre (dal 2 al 4) sono elementi dell'interfaccia; il livello posteriore è un caricatore, che è una GIF animata. Nel flusso normale mostri il caricatore (livello 1) mentre l'app si carica, poi al termine della procedura mostrerai gli altri livelli. Ma ecco la chiave: devi nascondere la GIF animata.
Ma perché devo nasconderlo?!
Ottima domanda. In un mondo perfetto, il browser semplicemente controllava la visibilità della GIF per te ed eviterà di colorare automaticamente. Purtroppo, controllare se la GIF animata è oscurata o visibile sullo schermo in genere è più costoso rispetto alla semplice verniciatura, pertanto viene verniciata.
Nel migliore dei casi, la GIF si trova nel suo livello e il browser deve solo dipingerla e caricarla nella GPU. Nel peggiore dei casi, però, tutti gli elementi potrebbero essere raggruppati in un unico livello e il browser deve ricreare ogni singolo elemento. Al termine, deve comunque caricare tutto nella GPU. Tutto questo avviene su ogni fotogramma della GIF, a prescindere dal fatto che l'utente non riesca nemmeno a vedere la GIF.
Sui computer probabilmente puoi far franca questo tipo di comportamento di disegno, perché le CPU e le GPU sono più potenti e c'è molta larghezza di banda per il trasferimento dei dati tra le due. Sui dispositivi mobili, tuttavia, la verniciatura è estremamente costosa, quindi devi fare molta attenzione.
Quali browser sono interessati?
Come spesso accade, i comportamenti variano da browser a browser. Oggi Chrome, Safari e Opera vengono ridipinti, anche se la GIF è oscurata. Firefox, invece, capisce che la GIF è oscurata e non deve essere ridipinta. Internet Explorer rimane qualcosa di una scatola nera, e anche in IE11, dato che gli strumenti F12 sono ancora in fase di sviluppo, non c'è indicazione che sia in corso una ridipintura.
Come faccio a capire se ho questo problema?
Il modo più semplice è utilizzare "Mostra rettangoli dipinti" in Chrome DevTools. Carica DevTools e premi l'ingranaggio nell'angolo in basso a destra () e scegli Mostra rettangoli di disegno nella sezione Rendering.
Ora non devi fare altro che cercare un rettangolo rosso come questo:
La piccola casella rossa sullo schermo mostra che Chrome sta ridipingendo qualcosa. Sai che c'è una GIF di caricamento nascosta dietro gli altri elementi, quindi quando vedi una casella rossa come questa devi nascondere gli elementi visibili e controllare se hai lasciato la GIF animata in rotazione. In questo caso devi aggiungere CSS o JavaScript per applicare display: none
o visibility: hidden
all'elemento principale o all'elemento stesso. Ovviamente se si tratta solo di un'immagine di sfondo, dovresti assicurarti di rimuoverla.
Se vuoi vedere un esempio di questo comportamento in un sito attivo, dai un'occhiata ad Allegro, dove l'immagine di ogni prodotto ha una GIF di caricamento oscurata anziché nascosta.
Conclusione
Raggiungere 60 FPS significa fare solo ciò che serve per visualizzare la pagina e non di più. Rimuovere le vernici in eccesso è un passaggio fondamentale per raggiungere questo obiettivo. Le GIF animate lasciate in esecuzione possono attivare colori non necessari, qualcosa che puoi trovare e sottoporre a debug facilmente con lo strumento Mostra rettangoli di disegno di DevTools.
Non hai lasciato in esecuzione per sempre la GIF animata di questo caricatore di gattini, vero?