Hakkerointi CSS-animaation tila ja toistoaika PlatoBlockchain Data Intelligence. Pystysuuntainen haku. Ai.

Hakkerointi CSS-animaation tila ja toistoaika

Vain CSS-käyttöinen Wolfenstein on pieni projekti, jonka tein muutama viikko sitten. Se oli kokeilu CSS 3D -muunnoksilla ja -animaatioilla.

Innoittamana FPS demo ja toinen Wolfenstein CodePen, päätin rakentaa oman versioni. Se perustuu löyhästi alkuperäisen Wolfenstein 1D -pelin jaksoon 9 – Floor 3.

Editor: Tämä peli vaatii tarkoituksella nopeaa reagointia Game Over -näytön välttämiseksi.

Tässä läpikäyntivideo:

[Upotetun sisällön]

Lyhyesti sanottuna projektini on vain huolellisesti käsikirjoitettu pitkä CSS-animaatio. Lisäksi muutama tapaus valintaruudun hakkerointi.

:checked ~ div { animation-name: spin; }

Ympäristö koostuu 3D-ruudukosta ja animaatiot ovat enimmäkseen tavallisia 3D-käännöksiä ja rotaatioita. Ei mitään todella hienoa.

Kaksi ongelmaa oli kuitenkin erityisen hankala ratkaista:

  • Toista "aselaukaisu"-animaatio aina, kun pelaaja napsauttaa vihollista.
  • Kun nopeasti liikkuva pomo sai viimeisen osuman, siirry dramaattiseen hidastukseen.

Teknisellä tasolla tämä tarkoitti seuraavaa:

  • Toista animaatio uudelleen, kun seuraava valintaruutu on valittuna.
  • Hidasta animaatiota, kun valintaruutu on valittuna.

Itse asiassa kumpaakaan ei projektissani ratkaistu kunnolla! Joko päädyin käyttämään kiertotapoja tai vain luovutin.

Toisaalta pienen kaivamisen jälkeen löysin lopulta avaimen molempiin ongelmiin: CSS-animaatioiden ominaisuuksien muuttamisen. Tässä artikkelissa tutkimme aihetta lisää:

  • Paljon interaktiivisia esimerkkejä.
  • Dissektiot: miten kukin esimerkki toimii (tai ei toimi)?
  • Kulissien takana: miten selaimet käsittelevät animaatiotiloja?

Anna minun "heittä tiiliäni".

Ongelma 1: Toistan animaatiota

Ensimmäinen esimerkki: "vain toinen valintaruutu"

Ensimmäinen intuitioni oli "lisää vain toinen valintaruutu", joka ei toimi:

Jokainen valintaruutu toimii erikseen, mutta ei molempia yhdessä. Jos yksi valintaruutu on jo valittuna, toinen ei enää toimi.

Näin se toimii (tai "ei toimi"):

  1. - animation-name of <div> is none oletuksena.
  2. Käyttäjä napsauttaa yhtä valintaruutua, animation-name tulee spin, ja animaatio alkaa alusta.
  3. Hetken kuluttua käyttäjä klikkaa toista valintaruutua. Uusi CSS-sääntö astuu voimaan, mutta animation-name is yhä spin, mikä tarkoittaa, että animaatiota ei lisätä eikä poisteta. Animaatio vain jatkaa toistoa kuin mitään ei olisi tapahtunut.

Toinen esimerkki: "animaation kloonaaminen"

Yksi toimiva lähestymistapa on kloonata animaatio:

#spin1:checked ~ div { animation-name: spin1; }
#spin2:checked ~ div { animation-name: spin2; }

Näin se toimii:

  1. animation-name is none aluksi.
  2. Käyttäjä napsauttaa "Pyörä!", animation-name tulee spin1. Animaatio spin1 aloitetaan alusta, koska se on juuri lisätty.
  3. Käyttäjä napsauttaa "Pyörä uudelleen!", animation-name tulee spin2. Animaatio spin2 aloitetaan alusta, koska se on juuri lisätty.

Huomaa, että vaiheessa 3, spin1 poistetaan CSS-sääntöjen järjestyksen vuoksi. Se ei toimi, jos "Pyörä uudelleen!" tarkistetaan ensin.

Kolmas esimerkki: "lisätään sama animaatio"

Toinen toimiva lähestymistapa on "liitä sama animaatio":

#spin1:checked ~ div { animation-name: spin; }
#spin2:checked ~ div { animation-name: spin, spin; }

Tämä on samanlainen kuin edellinen esimerkki. Voit itse asiassa ymmärtää käyttäytymisen näin:

#spin1:checked ~ div { animation-name: spin1; }
#spin2:checked ~ div { animation-name: spin2, spin1; }

Huomaa, että kun "Pyörä uudelleen!" on valittuna, vanhasta käynnissä olevasta animaatiosta tulee toinen animaatio uudessa luettelossa, mikä voi olla epäintuitiivinen. Suora seuraus on: temppu ei toimi, jos animation-fill-mode is forwards. Tässä on demo:

Jos ihmettelet, miksi näin on, tässä on joitain vihjeitä:

  • animation-fill-mode is none oletuksena, mikä tarkoittaa "Animaatiolla ei ole vaikutusta ollenkaan, jos sitä ei toisteta".
  • animation-fill-mode: forwards; tarkoittaa "Kun animaatio on toistettu, sen on pysyttävä viimeisessä avainkehyksessä ikuisesti".
  • spin1Päätös kumoaa aina spin2koska spin1 näkyy myöhemmin luettelossa.
  • Oletetaan, että käyttäjä napsauttaa "Pyörä!", odottaa täyttä pyöräytystä ja sitten napsauttaa "Pyörä uudelleen!". Tällä hetkellä. spin1 on jo valmis, ja spin2 vasta alkaa.

Keskustelu

Nyrkkisääntö: olemassa olevaa CSS-animaatiota ei voi "käynnistää uudelleen". Sen sijaan haluat lisätä ja toistaa uuden animaation. Tämän voi vahvistaa W3C spec:

Kun animaatio on alkanut, se jatkuu, kunnes se päättyy tai animaation nimi poistetaan.

Nyt kun verrataan kahta viimeistä esimerkkiä, mielestäni käytännössä "kloonausanimaatioiden" pitäisi usein toimia paremmin, varsinkin kun CSS-esiprosessori on saatavilla.

Ongelma 2: Hidastus

Voidaan ajatella, että animaation hidastaminen on vain pidemmän pituuden asettaminen animation-duration:

div { animation-duration: 0.5s; }
#slowmo:checked ~ div { animation-duration: 1.5s; }

Todellakin, tämä toimii:

… vai onko?

Muutamalla säädöllä ongelman pitäisi olla helpompi nähdä.

Kyllä, animaatio on hidastettu. Ja ei, se ei näytä hyvältä. Koira (melkein) "hyppää" kun vaihdat valintaruutua. Lisäksi koira näyttää hyppäävän satunnaiseen asentoon alkuperäisen aseman sijaan. Kuinka niin?

Se olisi helpompi ymmärtää, jos ottaisimme käyttöön kaksi "varjoelementtiä":

Molemmat varjoelementit käyttävät samoja animaatioita eri tavoin animation-duration. Eikä valintaruutu vaikuta niihin.

Kun vaihdat valintaruutua, elementti vaihtaa välittömästi kahden varjoelementin tilojen välillä.

Lainaaminen W3C spec:

Animaatio-ominaisuuksien arvojen muutokset animaation ollessa käynnissä ovat ikään kuin animaatiolla olisi kyseiset arvot sen alkaessa.

Tämä on seurausta kansalaisuudeton suunnittelu, jonka avulla selaimet voivat helposti määrittää animoidun arvon. Varsinainen laskenta on kuvattu tätä ja tätä.

Toinen yritys

Yksi idea on keskeyttää nykyinen animaatio ja lisätä sitten hitaampi animaatio, joka ottaa vallan sieltä:

div {
  animation-name: spin1;
  animation-duration: 2s;
}

#slowmo:checked ~ div {
  animation-name: spin1, spin2;
  animation-duration: 2s, 5s;
  animation-play-state: paused, running;
}

Joten se toimii:

… vai onko?

Se hidastuu, kun napsautat "Slowmo!". Mutta jos odotat täyttä ympyrää, näet "hypyn". Itse asiassa se hyppää aina asentoon, kun "Slowmo!" napsautetaan.

Syynä on, että meillä ei ole a from avainkehys määritelty – eikä meidän pitäisi. Kun käyttäjä napsauttaa "Slowmo!", spin1 on pysähtynyt jossain kohdassa, ja spin2 alkaa täsmälleen samasta paikasta. Emme yksinkertaisesti voi ennustaa sitä asemaa etukäteen… vai voimmeko?

Toimiva Ratkaisu

Me voimme! Käyttämällä mukautettua ominaisuutta voimme kaapata kulman ensimmäisessä animaatiossa ja siirtää sen sitten toiseen animaatioon:

div {
  transform: rotate(var(--angle1));
  animation-name: spin1;
  animation-duration: 2s;
}

#slowmo:checked ~ div {
  transform: rotate(var(--angle2));
  animation-name: spin1, spin2;
  animation-duration: 2s, 5s;
  animation-play-state: paused, running;
}

@keyframes spin1 {
  to {
    --angle1: 360deg;
  }
}

@keyframes spin2 {
  from {
    --angle2: var(--angle1);
  }
  to {
    --angle2: calc(var(--angle1) + 360deg);
  }
}

Huomautus: @property käytetään tässä esimerkissä, joka on kaikki selaimet eivät tue.

"Täydellinen" ratkaisu

Edellisessä ratkaisussa on varoitus: "slowmosta poistuminen" ei toimi hyvin.

Tässä parempi ratkaisu:

Tässä versiossa hidastettua kuvaa voidaan syöttää tai siitä poistua saumattomasti. Myöskään kokeellista ominaisuutta ei käytetä. Onko se siis täydellinen ratkaisu? Kyllä ja ei.

Tämä ratkaisu toimii kuten "vaihteiden vaihtaminen":

  • Vaihteet: niitä on kaksi <div>s. Toinen on toisen vanhempi. Molemmilla on spin animaatio, mutta erilainen animation-duration. Elementin lopullinen tila on molempien animaatioiden kertymä.
  • Vaihto: Alussa vain yksi <div> animaatio on käynnissä. Toinen on tauolla. Kun valintaruutu on päällä, molemmat animaatiot vaihtavat tilojaan.

Vaikka pidän todella tuloksesta, siinä on yksi ongelma: se on mukava hyödyntää spin animaatio, joka ei yleensä toimi muun tyyppisissä animaatioissa.

Käytännöllinen ratkaisu (JS:n kanssa)

Yleisissä animaatioissa on mahdollista saada hidastettu toiminto pienellä JavaScriptillä:

Nopea selitys:

  • Mukautettua ominaisuutta käytetään animaation edistymisen seuraamiseen.
  • Animaatio "käynnistetään uudelleen", kun valintaruutua vaihdetaan.
  • JS-koodi laskee oikean animation-delay varmistaaksesi saumattoman siirtymän. minä suosittelen Tämä artikkeli jos et tunne negatiivisia arvoja animation-delay.

Voit nähdä tämän ratkaisun "uudelleenkäynnistyksen animaation" ja "vaihteenvaihdon" yhdistelmänä.

Tässä on tärkeää seurata animaation edistymistä oikein. Ratkaisut ovat mahdollisia, jos @property ei ole saatavilla. Esimerkkinä tämä versio käyttää z-index edistymisen seuraamiseksi:

Sivuhuomautus: alun perin yritin myös luoda vain CSS-versiota, mutta en onnistunut. Vaikka en ole 100% varma, luulen sen johtuvan siitä animation-delay is ei animoitavissa.

Tässä on versio minimaalisella JavaScriptillä. Vain "syöttäminen hitaasti" toimii.

Kerro minulle, jos onnistut luomaan toimivan CSS-version!

Hidastettu mikä tahansa animaatio (JS:n kanssa)

Lopuksi haluaisin jakaa ratkaisun, joka toimii (melkein) missä tahansa animaatiossa, jopa monimutkaisissakin animaatioissa @keyframes:

Periaatteessa sinun on lisättävä animaation edistymisen seuranta ja laskettava sitten huolellisesti animation-delay uutta animaatiota varten. Joskus voi kuitenkin olla hankalaa (mutta mahdollista) saada oikeat arvot.

Esimerkiksi:

  • animation-timing-function ei ole linear.
  • animation-direction ei ole normal.
  • useita arvoja sisään animation-name eri animation-durationja animation-delayN.

Tämä menetelmä on myös kuvattu tätä varten Web Animations API.

Kiitokset

Aloitin tällä polulla, kun törmäsin vain CSS-projekteihin. Jotkut olivat herkkä taideteos, ja jotkut olivatkin monimutkaiset keinot. Suosikkini ovat ne, joissa on 3D-objekteja, esimerkiksi tämä pomppiva pallo ja tämä pakkauskuutio.

Alussa minulla ei ollut aavistustakaan, miten nämä tehtiin. Myöhemmin luin ja opin paljon tämä mukava opetusohjelma Ana Tudorilta.

Kuten kävi ilmi, 3D-objektien rakentaminen ja animointi CSS:llä ei eroa paljonkaan sen tekemisestä tehosekoitin, vain hieman erilaisella maulla.

Yhteenveto

Tässä artikkelissa tarkastelimme CSS-animaatioiden käyttäytymistä, kun an animate-* omaisuutta muutetaan. Erityisesti kehitimme ratkaisuja "animaation toistamiseen" ja "animaatiohidastukseen".

Toivottavasti tämä artikkeli on kiinnostava. Kerro mielipiteesi!

Aikaleima:

Lisää aiheesta CSS-temppuja