CSS Trick: background animato sul logo
Per ottenere l’effetto di gradiente rotante che si vede attualmente, ho inizialmente sperimentato con un po’ di JavaScript, in questo modo:
document.addEventListener("DOMContentLoaded", () => {
const DEG_STEP = 2.8125 // equivale a 360 / 128;
const INTERVAL = 62.5 // equivale a 8000 / 128
let deg = 42;
let logo = document.querySelector(".page__logo-inner");
setInterval(() => {
deg += DEG_STEP;
deg %= 360;
logo.style["background-image"] = `linear-gradient(${deg}deg, rgb(247, 115, 241), rgb(16, 180, 215))`;
}, INTERVAL)
});
All’apertura della pagina, quindi, parte il setInterval, che a cadenza di 62.5 millisecondi modifica lo stile background-image, ruotando di fatto il linear-gradient.
Il loop dura 8 secondi. In 8 secondi vengono disegnati 128 fotogrammi, e ad ogni fotogramma la rotazione avanza di 2.8125 gradi.
Funzionava tutto perfettamente, ma avevo notato un problema: quando aprivo gli strumenti di sviluppo, l’utilizzo della CPU si impennava.
Questo succedeva perché nel tab Elements degli strumenti di sviluppo è visibile il DOM della pagina, con gli stili inline visibili in chiaro.
Lo stile del tag con classe .page__logo-inner, infatti, viene costantemente aggiornato, e il browser consuma CPU per visualizzare le modifiche, che, come detto prima, avvengono ogni 62.5 millisecondi. Probabilmente per il 99,99% degli utenti questo non rappresenta un vero problema, ma ho voluto comunque provare a risolverlo.
Ho deciso, quindi, di implementare lo stesso loop usando opportunamente il CSS al posto di JavaScript.
Ho provato inizialmente a impostare 3 keyframes, in questo modo:
.page__logo-inner {
background-image: linear-gradient(42deg, rgb(247, 115, 241), rgb(16, 180, 215));
animation: logo_anim 8s linear infinite;
}
@keyframes logo_anim {
0% {
background-image: linear-gradient(42deg, rgb(247, 115, 241), rgb(16, 180, 215));
}
50% {
background-image: linear-gradient(222deg, rgb(247, 115, 241), rgb(16, 180, 215));
}
100% {
background-image: linear-gradient(42deg, rgb(247, 115, 241), rgb(16, 180, 215));
}
}
Mi aspettavo che il browser calcolasse tutti i fotogrammi mancanti e rendesse quindi l’animazione fluida, ma non ha funzionato. L’animazione, infatti, si componeva di soli 3 frame, senza alcuna interpolazione, come si può vedere nella gif qui sotto.
Occorreva quindi scrivere esplicitamente tutti e 128 i keyframe per ottenere lo stesso effetto avuto con JavaScript. In questo modo il browser non avrebbe dovuto eseguire alcun calcolo, ma soltanto leggere i valori pre-calcolati.
Ma non avevo alcuna intenzione di farlo a mano, così ho scritto un piccolo programma JS da far girare direttamente sulla console del browser, che mi producesse la regola CSS con tutti i keyframe in formato testuale, da copiare e incollare direttamente nel file CSS.
const STEPS = 128;
const START_DEG = 42;
const DEG_STEP = 2.8125;
let percent_step = 100 / STEPS;
let output = "@keyframes logo_anim {\n";
for (let i=0; i<STEPS; i++) {
let percent = i * percent_step;
let deg = (START_DEG + (i * DEG_STEP)) % 360;
output += `\t${percent.toFixed(2)}% {\n\t\tbackground-image: linear-gradient(${deg}deg, rgb(247, 115, 241), rgb(16, 180, 215));\n\t}\n`;
}
output += "}";
console.log(output);
A questo punto, dopo averlo fatto girare in console, è bastato copiare l’output stampato a video e incollarlo nel file CSS.
.page__logo-inner {
background-image: linear-gradient(42deg, rgb(247, 115, 241), rgb(16, 180, 215));
animation: logo_anim 8s linear infinite;
}
@keyframes logo_anim {
0.00% {
background-image: linear-gradient(42deg, rgb(247, 115, 241), rgb(16, 180, 215));
}
0.78% {
background-image: linear-gradient(44.8125deg, rgb(247, 115, 241), rgb(16, 180, 215));
}
1.56% {
background-image: linear-gradient(47.625deg, rgb(247, 115, 241), rgb(16, 180, 215));
}
/* ... */
97.66% {
background-image: linear-gradient(33.5625deg, rgb(247, 115, 241), rgb(16, 180, 215));
}
98.44% {
background-image: linear-gradient(36.375deg, rgb(247, 115, 241), rgb(16, 180, 215));
}
99.22% {
background-image: linear-gradient(39.1875deg, rgb(247, 115, 241), rgb(16, 180, 215));
}
}
Problema risolto! Adesso l’utilizzo della CPU resta basso anche aprendo gli strumenti di sviluppo.
È stato inviato e sarà moderato prima della pubblicazione.