Häkkimise CSS-animatsiooni olek ja taasesitusaeg PlatoBlockchain Data Intelligence. Vertikaalne otsing. Ai.

Häkkimise CSS-animatsiooni olek ja taasesitusaeg

Ainult CSS-iga Wolfenstein on väike projekt, mille tegin paar nädalat tagasi. See oli katse CSS-i 3D-teisenduste ja animatsioonidega.

Inspireerituna FPS demo ja teine Wolfensteini koodipliiats, otsustasin luua oma versiooni. See põhineb vabalt algse Wolfensteini 1D-mängu episoodil 9 – 3. korrus.

Toimetaja: see mäng nõuab tahtlikult kiiret reageerimist, et vältida Game Over ekraani.

Siin on läbimängitud video:

[Varjatud sisu]

Lühidalt, minu projekt pole midagi muud kui hoolikalt skriptitud pikk CSS-animatsioon. Lisaks mõned juhtumid märkeruudu häkkimine.

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

Keskkond koosneb 3D-ruudustikust ja animatsioonid on enamasti tavalised 3D-tõlked ja -pöörded. Ei midagi tõeliselt uhket.

Kahe probleemi lahendamine oli aga eriti keeruline:

  • Mängige "relvast tulistamise" animatsiooni alati, kui mängija klõpsab vaenlasel.
  • Kui kiiresti liikuv boss sai viimase löögi, sisestage dramaatiline aegluubis.

Tehnilisel tasandil tähendas see järgmist:

  • Kui järgmine märkeruut on märgitud, esitage animatsioon uuesti.
  • Aeglustage animatsiooni, kui märkeruut on märgitud.

Tegelikult polnud kumbki minu projektis korralikult lahendatud! Ma kas kasutasin lahendusi või lihtsalt loobusin.

Teisest küljest leidsin pärast mõningast kaevamist lõpuks mõlema probleemi võtme: CSS-i animatsioonide käitamise atribuutide muutmine. Selles artiklis uurime seda teemat lähemalt:

  • Palju interaktiivseid näiteid.
  • Lahkamised: kuidas iga näide töötab (või ei tööta)?
  • Kulisside taga: kuidas brauserid animatsiooni olekuid käsitlevad?

Lase mul "viska mu klotse".

Probleem 1: Animatsiooni taasesitamine

Esimene näide: "lihtsalt veel üks märkeruut"

Minu esimene intuitsioon oli "lihtsalt lisage veel üks märkeruut", mis ei tööta:

Iga märkeruut töötab eraldi, kuid mitte mõlemad koos. Kui üks märkeruut on juba märgitud, siis teine ​​enam ei tööta.

See toimib järgmiselt (või "ei tööta"):

  1. . animation-name of <div> is none vaikimisi.
  2. Kasutaja klõpsab ühel märkeruudul, animation-name muutub spinja animatsioon algab algusest.
  3. Mõne aja pärast klõpsab kasutaja teisel märkeruudul. Uus CSS-reegel jõustub, kuid animation-name is veel spin, mis tähendab, et animatsiooni ei lisata ega eemaldata. Animatsioon lihtsalt jätkab mängimist, nagu poleks midagi juhtunud.

Teine näide: "animatsiooni kloonimine"

Üks toimiv lähenemisviis on animatsiooni kloonimine:

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

Siin on, kuidas see toimib:

  1. animation-name is none esialgu.
  2. Kasutaja klõpsab nupul "Keeruta!", animation-name muutub spin1. Animatsioon spin1 alustatakse algusest, kuna see lisati just.
  3. Kasutaja klõpsab nupul "Pööra uuesti!", animation-name muutub spin2. Animatsioon spin2 alustatakse algusest, kuna see lisati just.

Pange tähele, et sammus nr 3 spin1 eemaldatakse CSS-i reeglite järjekorra tõttu. See ei tööta, kui "Keeruta uuesti!" kõigepealt kontrollitakse.

Kolmas näide: "sama animatsiooni lisamine"

Teine toimiv lähenemisviis on sama animatsiooni lisamine:

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

See on sarnane eelmisele näitele. Tegelikult saate käitumist mõista järgmiselt:

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

Pange tähele, et kui "Keeruta uuesti!" on märgitud, saab vanast jooksvast animatsioonist uues loendis teine ​​animatsioon, mis võib olla ebaintuitiivne. Otsene tagajärg on: trikk ei tööta, kui animation-fill-mode is forwards. Siin on demo:

Kui soovite teada, miks see nii on, on siin mõned vihjed:

  • animation-fill-mode is none vaikimisi, mis tähendab "Animatsioonil pole üldse mingit mõju, kui seda ei esitata".
  • animation-fill-mode: forwards; tähendab "Pärast animatsiooni esitamise lõppu peab see jääma igaveseks viimase võtmekaadri juurde".
  • spin1otsus on alati tühistatud spin2sellepärast spin1 kuvatakse loendis hiljem.
  • Oletame, et kasutaja klõpsab nupul "Keeruta!", ootab täielikku keerutamist ja seejärel klõpsab nupul "Keeruta uuesti!". Praegusel hetkel. spin1 on juba lõppenud ja spin2 alles algab.

Arutelu

Rusikareegel: olemasolevat CSS-animatsiooni ei saa "taaskäivitada". Selle asemel soovite lisada ja esitada uue animatsiooni. Seda võib kinnitada W3C spetsifikatsioon:

Kui animatsioon on alanud, jätkub see seni, kuni see lõpeb või animatsiooni nimi eemaldatakse.

Võrreldes nüüd kahte viimast näidet, arvan, et praktikas peaksid "kloonimisanimatsioonid" sageli paremini töötama, eriti kui CSS-i eelprotsessor on saadaval.

Probleem 2: Aegluubis

Võib arvata, et animatsiooni aeglustamine on lihtsalt pikema seadmise küsimus animation-duration:

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

Tõepoolest, see toimib:

… või teeb?

Mõne muudatusega peaks probleemi nägemine olema lihtsam.

Jah, animatsioon on aeglustunud. Ja ei, see ei näe hea välja. Koer (peaaegu) "hüppab" alati, kui märkeruutu lülitate. Lisaks tundub, et koer hüppab pigem juhuslikku asendisse kui algsesse asendisse. Kuidas?

Seda oleks lihtsam mõista, kui tutvustaksime kahte "varjuelementi":

Mõlemad varjuelemendid käitavad samu animatsioone erinevalt animation-duration. Ja neid märkeruut ei mõjuta.

Kui lülitate märkeruudu sisse, lülitub element koheselt kahe varielemendi olekute vahel.

Quotes W3C spetsifikatsioon:

Animatsiooni atribuutide väärtuste muudatused animatsiooni käitamise ajal rakenduvad nii, nagu oleks animatsioonil need väärtused selle algusest peale.

See järgib kodakondsuseta disain, mis võimaldab brauseritel animeeritud väärtust hõlpsasti määrata. Kirjeldatakse tegelikku arvutust siin ja siin.

Veel üks katse

Üks idee on praegune animatsioon peatada ja seejärel lisada aeglasem animatsioon, mis võtab selle üle:

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

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

Nii et see töötab:

… või teeb?

See aeglustub, kui klõpsate nupul "Slowmo!". Aga kui ootate täisringi, näete "hüpet". Tegelikult hüppab see alati asendisse, kui "Slowmo!" klõpsatakse.

Põhjus on selles, et meil pole a from võtmekaader määratletud – ja me ei peaks seda tegema. Kui kasutaja klõpsab "Slowmo!", spin1 on mõnes kohas peatatud ja spin2 algab täpselt samast positsioonist. Me lihtsalt ei saa seda positsiooni ette ennustada … või saame?

Töötav lahendus

Me saame! Kohandatud atribuuti kasutades saame jäädvustada nurga esimeses animatsioonis ja seejärel edastada selle teisele animatsioonile:

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);
  }
}

Märge: @property kasutatakse selles näites, mis on ei toeta kõik brauserid.

"Täiuslik" lahendus

Eelnevale lahendusele on lisatud hoiatus: aeglasest väljumine ei tööta hästi.

Siin on parem lahendus:

Selles versioonis saab aegluubis siseneda või väljuda sujuvalt. Samuti ei kasutata eksperimentaalset funktsiooni. Kas see on siis ideaalne lahendus? Jah ja ei.

See lahendus toimib nagu "käikude vahetamine":

  • Hammasrattad: neid on kaks <div>s. Üks on teise vanem. Mõlemal on spin animatsioon, kuid erinevalt animation-duration. Elemendi lõplik olek on mõlema animatsiooni kogunemine.
  • Vahetamine: alguses ainult üks <div> selle animatsioon töötab. Teine on peatatud. Kui märkeruut on sisse lülitatud, vahetavad mõlemad animatsioonid olekut.

Kuigi tulemus mulle väga meeldib, on üks probleem: see on selle kena ärakasutamine spin animatsioon, mis muud tüüpi animatsioonide puhul üldiselt ei tööta.

Praktiline lahendus (koos JS-iga)

Üldiste animatsioonide puhul on võimalik aegluubis funktsioon saavutada vähese JavaScriptiga:

Kiire selgitus:

  • Animatsiooni edenemise jälgimiseks kasutatakse kohandatud atribuuti.
  • Animatsioon "taaskäivitatakse", kui märkeruut on sisse lülitatud.
  • JS-kood arvutab õige animation-delay et tagada sujuv üleminek. Ma soovitan Käesoleva artikli kui te ei ole kursis negatiivsete väärtustega animation-delay.

Seda lahendust saate vaadelda "animatsiooni taaskäivitamise" ja "käiguvahetuse" lähenemisviisi hübriidina.

Siin on oluline animatsiooni edenemist õigesti jälgida. Lahendused on võimalikud, kui @property pole saadaval. Näiteks see versioon kasutab z-index edenemise jälgimiseks:

Kõrvalmärkus: algselt proovisin luua ka ainult CSS-i versiooni, kuid see ei õnnestunud. Kuigi see pole 100% kindel, arvan, et see on sellepärast animation-delay is ei ole animeeritav.

Siin on versioon minimaalse JavaScriptiga. Töötab ainult aeglasesse sisenemine.

Palun andke mulle teada, kui teil õnnestub luua töötav ainult CSS-i versioon!

Aeglane mis tahes animatsioon (JS-iga)

Lõpetuseks tahaksin jagada lahendust, mis töötab (peaaegu) iga animatsiooni puhul, isegi mitme keerulise animatsiooni puhul @keyframes:

Põhimõtteliselt peate lisama animatsiooni edenemise jälgija ja seejärel hoolikalt arvutama animation-delay uue animatsiooni jaoks. Mõnikord võib aga õigete väärtuste leidmine olla keeruline (kuid võimalik).

Näiteks:

  • animation-timing-function ei ole linear.
  • animation-direction ei ole normal.
  • mitu väärtust sisse animation-name erinevate animation-durations ja animation-delayS.

Seda meetodit kirjeldatakse ka siin jaoks Veebianimatsioonide API.

Tunnustused

Alustasin seda teed pärast ainult CSS-i projektidega kokku puutumist. Mõned olid õrn kunstiteos, ja mõned olid keerulised vahendid. Minu lemmikud on need, mis hõlmavad 3D-objekte, näiteks see põrkav pall ja see pakkekuut.

Alguses polnud mul õrna aimugi, kuidas need tehtud on. Hiljem lugesin ja õppisin palju see kena õpetus Ana Tudorilt.

Nagu selgus, ei erine CSS-iga 3D-objektide ehitamine ja animeerimine palju selle tegemisest segisti, lihtsalt veidi teistsuguse maitsega.

Järeldus

Selles artiklis uurisime CSS-animatsioonide käitumist, kui animate-* vara muudetakse. Eelkõige töötasime välja lahendused “animatsiooni taasesitamiseks” ja “animatsiooni aeglaseks liikumiseks”.

Loodan, et see artikkel on teile huvitav. Palun andke mulle teada oma arvamusest!

Ajatempel:

Veel alates CSSi trikid