Dezvoltare de animatii cu CSS si JS

Costruirea de animatii pentru un website este un proces de continuu de iterare.

De la identificarea elementelor care pot fi dinamice si animate in design-ul unui website pana la transpunerea si finalizarea acestor idei in programare, pot trece prin multiple variante, unele simple si altele crazy, dar intotdeauna gasim o varinta care sa multumeasca nu numai clientul dar si pe noi.

Indiferent de cat de frumos arata design-ul, daca animatiile introduse nu sunt fluide atunci vizitatorii vor ramane cu o impresie urata care ii vor face sa nu mai revina pe website.

Vorbind despre Javascript si CSS, sunt foarte multe metode de a scrie cod care face acelasi lucru, dar unele sunt mai eficiente decat altele. Website-ul INOVEO a trecut printr-o sumedenie de schimbari de la lansarea lui in decembrie si pana acum, majoritatea axate pe imbunatatirea performantei care sa ne permita sa adaugam toate proiectele din portofoliul nostru stufos.

Unele din primele optimizari a fost reducerea elementelor care vor fi animate si ce elemente CSS vor fi afectate. Ca o regula simpla pentru programatori, este recomandat sa se animeze tag-urile CSS transform si opacity, iar alte tipuri sa fie evitate sau folosite intr-un numar redus. Acest lucru ne va permite sa rulam animatiile importante cu accelerare grafica. Aceasta schimbare va ajuta si cu unul din principalele bottleneck-uri de performanta la website-urile medii si mari: recalcularea style-ului de catre browser. Aceasta recalculare forteaza browser-ul sa redeseneze intreaga pagina, un process intensiv care va rezulta in miscari cu micro-stutters (sacadari) si cu framerate redus foarte variabil.

Un exemplu de schimbare pozitiva si simpla ar fi urmatorul cod CSS care va muta un div 300 de pixeli.

Before:

.clasa-animata{
  left: 0px;
  animation: move 1s ease-in-out;
}
@keyframes move{
  to {left: 300px}
}

After:

.clasa-animata{
  transform: translateX(0px);
  animation: move 1s ease-in-out;
}
@keyframes move{
  to {transform: translateX(300px)}
}

Animatiile realizate cu Javascript au potentialul de a intalni mai multe bottleneck-uri decat daca este folosit doar CSS, dar iti permite sa realizezi lucruri mult mai complicate. In cazul website-ului INOVEO am legat scroll-ul vertical cu miscarea orizontala a proiectelor pe homepage. Initial testele s-au facut cu un numar redus de proiecte, dar in momentul in care a fost finalizata introducerea tuturor proiectelor au probleme mari la animatia de scroll, in special pe calculatoare mai vechi sau slabe. S-a ajuns la concluzia ca intreg backend-ul trebuia sa fie rescris si optimizat daca voiam sa vedem noul nostru site intr-o stare de functionare buna.

Unul din tool-urile folosite pentru a verifica performanta si bottleneck-urile posibile ale unui website este DevTool-ul integrat in browsere, in acest caz cel din Chrome.
S-au identificat multiple puncte care se puteau imbunatati, unele dintre cele mai importante fiind: numarul de call-uri facute catre DOM cand rula functia pentru scroll, numarul de elemente afectate in timpul animatiei de scroll si ordinea efectuarii calculelor si modificarii elementelor din pagina.

Mai jos avem un screenshot la cum aratau graficele inainte de a se efectua toate schimbarile:

Codul JS a suferit modificari majore dar putem exemplifica intr-um mod simplu care poate fi inteles si de incepatori. Voi folosi JS simplu aici, dar noi avem implementat ES6 in codul sursa la website si recomand tuturor sa invete ES5/ES6.

Before:

function scrollHome(){
  var var1Elem, var2Elem, var3Scroll, var4Scroll;
  var1Elem = document.querySelectorAll(‘.elemente-mari’);
  var3Scroll = window.pageYOffset;
  for(var i=0; i<var1Elem.lenght; i++){
   var1Elem[i].style.transform = ‘translate3d(‘+var3Scroll+’px, 0px, 0px)’;
  }
  var2Elem = document.querySelectorAll(‘.elemente-mici’);
  var4Scroll = var3Scroll/2;
  for(var i=0; i<var2Elem.lenght; i++){
   var2Elem[i].style.transform = ‘translate3d(‘+var4Scroll+’px, 0px, 0px)’;
  }
}

After:

var var1Elem, var2Elem, var1Len, var3Len;
var1Elem = document.getElementsByClassName(‘elemente-mari’);
var2Elem = document.getElementsByClassName(‘elemente-mici’);
var1Len = var1Elem.lenght;
var2Len = var2Elem.lenght;
function scrollHome(){
  var var3Scroll = window.pageYOffset, var4Scroll = var3Scroll/2;
  for(var i=0; i<var1Len; i++){
   var1Elem[i].style.transform = ‘translate3d(‘+var3Scroll+’px, 0px, 0px)’;
  }
  for(var i=0; i<var1Len; i++){
   var2Elem[i].style.transform = ‘translate3d(‘+var4Scroll+’px, 0px, 0px)’;
  }
}

Modificarile efectuate dupa aceste teste au reusit sa reduca frametime-ul de la peste 100ms la aproape de 30ms, sa reduca significativ timpul de executare a codului JS, numarul de redesenari ale paginii fortate si a numarului de sacadari in timpul scroll-ului.

Website-ul INOVEO a vazut multe transformari de la lansare pana acum si vom continua sa-l imbunatatim in fiecare zi.