Kafli 19: Kvikun

Kvikun (e. animation) er þegar við látum eitthvað hreyfast eftir ákveðnum reglum. Í CSS er hægt að gera það með transition og animation eigindunum. Með því að nota hreyfingar getum við gert viðmót eðlilegra, vinalegra og skemmtilegra. Viðmót geta orðið fágaðari, þar sem við fjarlægjum „grófleikann“ sem getur orðið ef við breytum einhverju samstundis. Of mikið af hreyfingum er þó ekki eitthvað sem við viljum, það þarf ekki allt að hreyfast alltaf.

19.1 Umskipti

Með umskiptum (e. transition) látum við eitt gildi breytast í annað á skilgreindum tíma. Breytingin gerist ekki strax, það er einhver brúun á milli upphafs og endagildis. Við skilgreinum hvaða eigindi eigi að breyta, á hve löngum tíma og með hvaða hröðun. Vafrinn sér síðan um að brúa gildið miðað við það sem við viljum.

Umskipti virka þannig að vafri fylgist með gildi og ef við skilgreinum að það breytist (t.d. ef við setjum nýtt gildi með :hover) þá er gildinu ekki breytt samstundis. transition er shorthand fyrir:

/* transition: <property> <duration> <timing-function> <delay> */
/* color gildi mun breytast með línulegri hröðun á 250 millisek */
transition: color 250ms linear 0;

Hægt er að skilgreina fleiri en eitt umskipti með því að skipta á kommu, ,:

transition: color 250ms, background-color 250ms;

Með transition-property skilgreinum við með hvaða eigindi við fylgjumst. Það er leyfilegt að setja all sem gildi en þá er fylgst með breytingum á öllum eigindum og getur það valdið óþarfa hægagangi. Við viljum vera nákvæm í því hvað á að breytast og forðumst það því. Tíma er hægt að skilgreina í millisekúndum (250ms) eða sekúndum (1.25s).

a {
  background-color: #000;
  color: #fff;
  /*
  í staðinn fyrir að skipta beint úr svörtu í hvítt gerum
  við það á 250ms svo það verður ekkert „blikk“
  */
  transition: color 250ms, background-color 250ms;
}
a:hover {
  background-color: #fff;
  color: #000;
}

19.1.1 Hröðun

Hröðunarfall er skilgreint með rúmfræðilegri bezier kúrvu (e. cubic bezier curve) eða lykilorði (sem er tengt við ákveðna bezier kúrvu).

Dæmi um bezier kúrvu.

Mynd frá MDN:
https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function

Bezier kúrvur eru föll sem skilgreina hvernig gildi breytist yfir tíma: hver hröðun þess er. Ef við höfum línulega hröðun fer gildið frá upphafsgildi til lokagildis með nákvæmlega sama hlutfalli á hverja tímaeiningu. cubic-bezier(x1, y1, x2, y2) er fall í CSS sem leyfir okkur að skilgreina nákvæmlega hvernig kúrvan hagar sér en við notum yfirleitt lykilorð sem skilgreina mikið notaðar kúrvur.

Línuleg hröðun með linear lykilorði.

Hröðun með ease-in-out lykilorði.

Mynd frá MDN:
https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function

19.2 Animation

Með animation eigindinu getum við útbúið flóknari hreyfingar án þess að nota JavaScript. Við skilgreinum keyframes fyrir hreyfinguna með @keyframes at-reglunni. Hreiðraðar skipanir innan @keyframes hafa ekki selector heldur prósentugildi eða, lykilorðin from sem er jafngilt 0% eða to sem er jafngilt 100%. Gildin segja til um hvernig hreyfing lítur út á viðeigandi stað og mun vafri brúa á milli m.v. gefinn tíma og hröðun.

@keyframes fade {
  /* þegar hreyfing er í 0% er opacity: 0 */
  from {
    opacity: 1;
  }
  /* þegar hreyfing er í 50% er opacity: 0.4 */
  50% {
    opacity: 0.4;
  }
  /* þegar hreyfing er í 100% er opacity: 1 */
  to {
    opacity: 0;
  }
}

Við stýrum síðan hvernig hreyfing hagar sér með animation sem er shorthand fyrir:

Fyrir animation-direction getum við notað lykilorðin:

/*
animation: duration | timing-function | delay |  iteration-count |
           direction | fill-mode | play-state | name 
*/
animation: 2s ease 0 infinite alternate both running fade;
/* animation: duration | name */
animation: 3s fade;

19.3 Transform

Með transform eigindinu getum við gert breytingar á tvívíðu og þrívíðu rúmi hluta með því að nota translate, rotate, skew og scale. Lang flestar af þessum aðgerðum verða fluttar af vafra frá CPU yfir á GPU (graphics processing unit, sérstakur kubbur í tölvu sérhannaður til að vinna með grafík) og eru þessar aðgerir því miklu hagkvæmari en að reikna út gildi og teikna allt útlit vefs aftur ef við myndum t.d. nota position.

Ef við viljum færa hlut notum við transform: translate(x, y) til að færa á x og y-ás. Getum einnig gert í þrívíðu rúmi með transform: translate3d(x, y, z).

Ef við viljum stækka eða minnka hlut notum við transform: scale(ratio); þar sem ratio er hlutfall, 1.0 og hlutur er í venjulegri stærð (m.v. teiknað útlit), 0.5 og hann er helmingi minni, 2.0 og hann er tvisvar sinnum stærri.

19.4 Sjónarhorn

Þegar við gerum breytingar í þrívíðu rúmi þurfum við að skilgreina hversu langt frá notanda núllpunktur z-áss er, hver sjónarhorn (e. perspective) okkar er. Það gerum við með perspective eigindinu. Sjálfgefna gildið er none sem þýðir að fjarlægð frá z-ás er óskilgreind og allar þrívíðar breytingar munu ekki sjást.

19.5 Jank

Þegar við erum að vinna með hreyfingar viljum við halda þeim mjúkum og fínum, án þess að þær haltri eða líti skringilega út. Galdratalan í því samhengi eru 60fps eða 60 rammar á sekúndu. Það þýðir að hver vafrinn (eða það sem er að birta hreyfingu) hefur 16,67 millisekúndu per ramma til að gera alla þá útreikninga sem þarf til að láta næsta ramma birtast rétt. Ef við erum að gera of mikið á þessum tíma, t.d. hreyfa of marga hluti eða á óhagkvæman máta, þá förum við að taka eftir jank, hlutir hreyfast óeðlilega.

TIl að komast hjá jank þegar við búum til hreyfingar er ein einföld regla sem kemur okkur vel áleiðis: aðeins breyta opacity og transform þegar við hreyfum hluti. Að breyta öðrum eigindum mun valda því að GPU er ekki notað.

Einnig getum við notað will-change eigindið sem lætur vafra vita að við munum breyta ákveðnum eigindi og er þá hægt að gera viðeigandi ráðstafanir. Listin að gera vefi sem eru hraðir og nýta hagkvæmar leiðir er mikil list, hægt er að læra meira á Jank Free.