Üks asi, mis meid uue veebilehe ehitamisel segadusse ajas, olid morphed waves, mida näete lehekülgede eri kohtades. Meil oli palju ideid, kuidas neid ilma suure vaevata õigesti rakendada. Kuid enamik lahendusi olid aeglased ja me pidime nullist midagi ehitama, mis oleks kiirem kui juba olemasolevad raamatukogud.
Ettepanekud lahenduse kohta
Alustasime tavalise SVG objektiga, mida animeeriti erinevate raamatukogude abil. Kuna soovisime, et ühel lehel oleks 3 objekti, ei olnud tulemus nii rahuldav. Kõik animatsioonid olid lihtsalt aeglased - ühe SVG-objekti kõiki radu tuli uuendada väga lühikese aja jooksul, mis muutis kogu lehe aeglaseks nagu tigu. Me pidime tagasi lükkama lahenduse, kus dokumenti oli sisestatud puhas SVG. See jättis meile valida kahe teise lahenduse vahel.
The video
element oli teine võimalus. Alustasime kahe probleemiga:
- läbipaistev taust, mida ei saa kasutada kõige populaarsemate videoformaatide, näiteks .mp4 või .webm puhul,
- reageerimisvõime, mis oli tõeline probleem, sest videod ei ole sellisena skaleeritavad.
Otsustasime, et hoiame selle lahenduse tagaplaanil - "kui me ei leia midagi muud, siis valime selle".
Viimane võimalus oli kasutada lõuend
koos WebGL
renderdamine. See oli nii ebatavaline variant, sest me pidime kogu renderdamismehhanismi ise kujundama. Seda seetõttu, et meie morfilised lained olid kohandatud - see sundis meid disainima kohandatud lahendust Ja see oli variant, mida me tahtsime järgida ja millele me tõesti keskenduda.
Lahenduse arhitektuur
Alustame nullist. Mis oli see materjal, mida me pidime nende lainete ehitamiseks kasutama? Idee oli, et kõik lained olid SVG-faili suurusega 1×1 ja konkreetsed rajad, mis olid paigutatud ümber selle ala. Selle SVG animatsioon ehitati selle faili mõne olekuvormi abil. Nii et kõik animatsioonid olid esindatud failide kogumina, mis sisaldas kuju liikumise etappe.
Vaadake põhjalikumalt, mis on olekud - kõik teed on lihtsalt mingi massiivi, mille konkreetsed väärtused on paigutatud konkreetses järjekorras. Nende väärtuste muutmine konkreetsetes positsioonides selles massiivi sees muudab kuju selle konkreetsetes osades. Me võime seda lihtsustada järgmise näite abil:
seisund 1: [1, 50, 25, 40, 100]
seisund 2: [0, 75, -20, 5, 120]
seisund 3: [5, 0, -100, 80, 90]
Seega võime eeldada, et kuju, mida me tahame renderdada, koosneb 5 elemendiga massiivi, mis muutub lineaarse leevendusega teatud ajavahemike jooksul. Kui animatsioon lõpetab viimase etapi, algab see uuesti esimesest, et jätta meile mulje lõpmatu animatsioonist.
Aga... oodake - mis täpselt on eespool esitatud massiivi? Nagu ma mainisin, on see tee, mis vastutab konkreetse kuju kuvamise eest. Kogu maagia sisaldub d
omadus SVG tee. See omadus sisaldab komplekti "käske" kuju joonistamiseks ja igal käsul on mingid argumendid. Eespool mainitud massiivi moodustavad kõik nende käskude juurde kuuluvad väärtused (argumendid).
Ainus erinevus nende "riigifailide" vahel olid konkreetsete käskude väärtused, kuna käskude järjekord oli sama. Nii et kogu võlu seisnes kõigi väärtuste hankimises ja nende animeerimises.
Võlur nimega Füüsika
Eespool mainisin, et ainus võlu objekti animeerimisel on üleminekute loomine kuju kõigi etappide vahel. Küsimus on - kuidas seda teha canvas'iga?
Funktsioon, mida kõik, kes töötasid lõuend
peaks teadma, et requestAnimationFrame. Kui näete seda esimest korda, siis usun siiralt, et peaksite alustama selle lugemisega. Niisiis, asi selle funktsiooni puhul, mis meid huvitab, on argument - DOMHighResTimeStamp
. See näeb tõesti hirmuäratav välja, kuid praktikas ei ole sellest nii raske aru saada. Võime öelda, et see on ajamärk möödunud ajast alates esimesest renderdamisest.
Ok, aga mida me sellega teha saame? Kuna requestAnimationFrame
funktsiooni tuleks kutsuda rekursiivselt, saame juurdepääsu selle kutsete vahelisele ajalisele deltale. Ja siin me läheme teadusega! ⚛️ (ok, võib-olla ei ole raketiteadus... veel )
Füüsika õpetab meile, et vahemaa delta on võrdne aja delta ja kiiruse korrutisega. Meie puhul on kiirus konstantne, sest me tahame jõuda lõpp-punkti teatud aja jooksul. Niisiis, vaatame, kuidas me saame seda ülaltoodud olekute abil kujutada:
Oletame, et tahame nende seisundite vahel liikuda tuhande millisekundi jooksul, seega on kiiruse väärtused järgmised:
delta: [ -1, 25, -45, -35, 20]
kiirus: [-1/1000, 25/1000, -45/1000, -35/1000, 20/1000]
Ülaltoodud kiirus ütleb meile: iga millisekundi kohta suurendame väärtust -1/1000 võrra. Ja siin on punkt, kus me võime minna tagasi meie requestAnimationFrame
ja ajadelta. Konkreetse positsiooni väärtus, mida me tahame suurendada, on aeg delta korrutatud selle positsiooni kiirusega. Veel üks asi, mille saavutamine on probleemivabalt võimalik, on piirata väärtust nii, et see ei ületaks seda seisundit, kuhu ta läheb.
Kui üleminek lõpeb, kutsume teise ja nii edasi. Ja see ei tundu olevat nii raske rakendada, kuid üks peamisi reegleid on tarkvaraarendus on mitte kulutada aega asjadele, mis on juba rakendatud. Niisiis - me valisime väike raamatukogu mis võimaldab meil neid üleminekuid vaevata luua.
Nii lõime ühe animeeritud laine, mis näeb välja nagu elusolend.
Paar sõna kloonimise kujude kohta
Nagu näete, ei ole The Codest kaubamärgi lained üks animeeritud figuur. Need koosnevad paljudest sama kujuga, kuid erineva suuruse ja asendiga figuuridest. Selles sammus vaatame lühidalt, kuidas sellisel viisil dubleerida.
Seega võimaldab lõuendi kontekst meil mõõtkava joonistusala (kapoti all - võime öelda, et see korrutab kõik joonistatavatesse meetoditesse sisestatud mõõtmed "k"-ga, kus "k" on skaleerimistegur, mis on vaikimisi seatud "1"), make canvas tõlkida, see on nagu joonistusala ankurduspunkti muutmine. Ja me saame nende meetoditega ka nende olekute vahel hüpata: Salvesta ja taastada.
Need meetodid võimaldavad meil salvestada "nullmuudatuste" seisundi ja seejärel renderdada konkreetne arv laineid loopis õigesti skaleeritud ja tõlgitud lõuendiga. Kohe pärast seda saame minna tagasi salvestatud olekusse. See on kõik joonise kloonimise kohta. Palju lihtsam kui lammaste kloonimine, kas pole?
Kirss peal
Ma mainisin, et me lükkasime ühe võimaliku lahenduse tulemuslikkuse tõttu tagasi. Canvasiga variant on üsna kiire, kuid keegi ei öelnud, et seda ei saaks veel rohkem optimeerida. Alustame sellest, et me ei hooli tegelikult kujundite üleminekust, kui need on väljaspool brauseri vaateakentrit.
On veel üks brauseri API, mida programmeerijad armastasid - IntersectionObserver. See võimaldab meil jälgida lehe konkreetseid elemente ja käsitleda sündmusi, mis kutsutakse esile, kui need elemendid ilmuvad või kaovad vaateaknast. Praegu - meil on üsna lihtne olukord - loome nähtavuse seisundi, muudame seda tänu IntersectionObserver sündmuste käitlejatele ja lihtsalt lülitame renderdussüsteemi sisse/välja konkreetsete kujundite jaoks. Ja ... boom jõudlus on palju paranenud! Me renderdame ainult need asjad, mis on viewportil nähtavad.
Kokkuvõte
Asjade rakendamise viisi valimine on sageli raske valik, eriti kui olemasolevatel võimalustel näib olevat sarnased eelised ja puudused. Õige valiku tegemise võti on analüüsida kõiki neid ja välistada need, mida me peame vähem kasulikuks. Kõik ei ole selge - mõni lahendus nõuab rohkem aega kui teised, kuid see võib olla lihtsamini optimeeritav või paremini kohandatav.
Kuigi uusi JS-raamatukogusid ilmub peaaegu iga minut, on asju, mida nad ei suuda lahendada. Ja seepärast peaks iga front-end insener (ja mitte ainult nemad) tundma brauseri APIsid, olema kursis tehniliste uudistega ja vahel lihtsalt mõtlema, et "kuidas näeks minu selle raamatukogu implementatsioon välja, kui ma peaksin seda tegema?". Kui meil on rohkem teadmisi brauserite kohta, saame ehitada tõeliselt fantaasiarikkaid asju, teha häid otsuseid kasutatavate tööriistade kohta ja saada enesekindlamaks oma kood.
Loe edasi:
– Ruby 3.0. Ruby ja vähemtuntud privaatsuskontrolli meetodid
– Ole vait ja võta oma raha #1: Varjatud kulud ja tegelik paindlikkus tootearendusprotsessis
– CTO väljakutsed - tarkvaratoodete laiendamine ja arendamine