Yksi asia, joka sai meidät hämmentymään, kun rakensimme uutta verkkosivustoamme, olivat morphed waves, joita voit nähdä eri paikoissa sivuilla. Meillä oli monia ideoita siitä, miten toteuttaa ne oikealla tavalla ilman suurta vaivaa. Useimmat ratkaisut olivat kuitenkin hitaita, ja meidän oli rakennettava tyhjästä jotain, joka olisi nopeampi kuin jo olemassa olevat kirjastot.
Ratkaisuehdotukset
Aloitimme tavallisesta SVG-objektista, jota animoitiin eri kirjastojen avulla. Koska halusimme saada 3 objektia yhdelle sivulle, tulos ei ollut kovin tyydyttävä. Kaikki animaatiot olivat vain hitaita - yhden SVG-objektin kaikki polut oli päivitettävä todella lyhyessä ajassa, mikä teki koko sivusta hitaan kuin etana. Meidän oli hylättävä ratkaisu, jossa pelkkä SVG lisättiin asiakirjaan. Jäljelle jäi kaksi muuta ratkaisua, joista valita.
The video
elementti oli toinen vaihtoehto. Meillä oli aluksi kaksi ongelmaa:
- läpinäkyvä tausta, jota ei voi käyttää suosituimmissa videoformaateissa, kuten .mp4 tai .webm,
- reagointikyky, mikä oli todellinen ongelma, koska videot eivät ole sellaisenaan skaalautuvia.
Päätimme pitää tämän ratkaisun taka-alalla - "jos emme löydä mitään muuta, valitsemme tämän".
Viimeinen vaihtoehto oli käyttää kangas
kanssa WebGL
renderointi. Se oli niin epätavallinen vaihtoehto, koska meidän oli suunniteltava kaikki renderöintimekaniikka itse. Se johtui siitä, että morfiset aallot, joita meillä oli, olivat mukautettuja - se pakotti meidät suunnittelemaan mukautetun ratkaisun Ja se oli vaihtoehto, jota halusimme seurata ja johon halusimme todella keskittyä.
Ratkaisun arkkitehtuuri
Aloitetaan tyhjästä. Mitä materiaalia meidän piti käyttää näiden aaltojen rakentamiseen? Ajatuksena oli, että kaikki aallot olivat SVG-tiedosto, jonka koko oli 1×1, ja tietyt polut sijoitettiin tämän alueen ympärille. Tämän SVG:n animaatio rakennettiin jonkinlaisilla tiloilla tähän tiedostoon. Kaikki animaatiot esitettiin siis joukolla tiedostoja, jotka sisälsivät muodon liikuttamisen vaiheet.
Tutustu tarkemmin siihen, mitä tilat ovat - kaikki polut ovat vain eräänlainen joukko, jossa on tiettyjä arvoja tietyssä järjestyksessä. Näiden arvojen muuttaminen tietyissä paikoissa tässä arrayssä muuttaa muotoa sen tietyissä osissa. Voimme yksinkertaistaa tätä seuraavan esimerkin avulla:
tila 1: [1, 50, 25, 40, 100]
tila 2: [0, 75, -20, 5, 120]
tila 3: [5, 0, -100, 80, 90]
Voimme siis olettaa, että muoto, jonka haluamme renderöidä, koostuu 5 elementtiä sisältävästä matriisista, joka muuttuu lineaarisen kevennyksen myötä tietyin aikavälein. Kun animaatio lopettaa viimeisen vaiheen, se alkaa uudelleen ensimmäisestä vaiheesta, jotta saamme vaikutelman loputtomasta animaatiosta.
Mutta... odota - mikä on edellä esitetty joukko? Kuten mainitsin, se on polku, joka on vastuussa tietyn muodon näyttämisestä. Kaikki taika sisältyy d
ominaisuutta SVG:n polusta. Tämä ominaisuus sisältää joukon "komentoja" muodon piirtämiseksi, ja jokaisella komennolla on eräänlaiset argumentit. Edellä mainittu joukko koostuu kaikista näihin komentoihin liitetyistä arvoista (argumenteista).
Ainoa ero näiden "tilatiedostojen" välillä oli tiettyjen komentojen arvot, koska komentojen järjestys oli sama. Kaikki taikuus oli siis kaikkien arvojen hankkimista ja niiden animointia.
Ohjattu toiminto nimeltään Physics
Edellä mainitsin, että ainoa taika objektin animoinnissa on siirtymien luominen muodon kaikkien vaiheiden välillä. Kysymys kuuluukin - miten se tehdään canvasilla?
Toiminto, jota kaikki, jotka työskentelivät kangas
pitäisi tietää on requestAnimationFrame. Jos näet tämän ensimmäistä kertaa, uskon vilpittömästi, että sinun pitäisi aloittaa lukemalla tämä. Tässä funktiossa meitä kiinnostaa siis argumentti - DOMHighResTimeStamp
. Se näyttää todella pelottavalta, mutta käytännössä se ei ole niin vaikea ymmärtää. Voimme sanoa, että se on aikaleima ensimmäisestä renderöinnistä kuluneesta ajasta.
Okei, mutta mitä voimme tehdä tällä? Koska requestAnimationFrame
funktiota pitäisi kutsua rekursiivisesti, voimme käyttää sen kutsujen välistä aikaväliä. Ja nyt mennään tieteen pariin! ⚛️ (okei, ei ehkä rakettitiedettä... vielä ).
Fysiikka opettaa meille, että etäisyyden delta on yhtä suuri kuin ajan delta kerrottuna nopeudella. Meidän tapauksessamme nopeus on vakio, koska haluamme saavuttaa päätepisteen tietyssä ajassa. Katsotaanpa siis, miten voimme esittää sen yllä olevilla tiloilla:
Sanotaan, että haluamme siirtyä näiden tilojen välillä tuhannessa millisekunnissa, joten nopeusarvot ovat seuraavat:
delta: [ -1, 25, -45, -35, 20]
nopeus: [-1/1000, 25/1000, -45/1000, -35/1000, 20/1000]
Yllä oleva nopeus kertoo meille: jokaista millisekuntia kohden lisätään arvoa -1/1000. Ja tässä on kohta, jossa voimme palata meidän requestAnimationFrame
ja ajan delta. Tietyn aseman arvo, jota haluamme kasvattaa, on aika delta kerrottuna sen aseman nopeudella. Vielä yksi asia, joka saavutetaan ongelmitta, on rajoittaa arvoa niin, ettei se ylitä tilaa, johon se on menossa.
Kun siirtymä päättyy, kutsumme uuden siirtymän ja niin edelleen. Eikä se näytä olevan niin vaikea toteuttaa, mutta yksi tärkeimmistä säännöistä on seuraava ohjelmistokehitys ei ole käyttää aikaa asioihin, jotka on jo toteutettu. Joten - valitsimme pieni kirjasto jonka avulla voimme luoda nämä siirtymät vaivattomasti.
Näin loimme yhden animoidun aallon, joka näyttää elävältä olennolta.
Muutama sana muotojen kloonauksesta
Kuten näet, The Codest-merkkiset aallot eivät ole yksi animoitu hahmo. Ne koostuvat monista hahmoista, joilla on sama muoto mutta eri koko ja asento. Tässä vaiheessa tarkastelemme nopeasti, miten monistetaan tällaisella tavalla.
Canvas-kontekstin avulla voimme siis mittakaavan piirtoalue (konepellin alla - voimme sanoa, että se moninkertaistaa kaikki piirtomenetelmiin syötetyt mitat "k:lla", jossa "k" on skaalauskerroin, joka on oletusarvoisesti asetettu arvoon "1"), make canvas käännetty, se on kuin vaihtaisi piirtoalueen ankkuripistettä. Ja voimme myös hypätä näiden tilojen välillä näillä menetelmillä: save ja palauta.
Näiden menetelmien avulla voimme tallentaa "nollamuutosten" tilan ja renderöidä tietyn määrän aaltoja silmukassa oikein skaalattuna ja käännettynä kankaalla. Heti tämän jälkeen voimme palata tallennettuun tilaan. Siinä kaikki hahmon kloonauksesta. Paljon helpompaa kuin lampaiden kloonaaminen, eikö olekin?
Kirsikka päälle
Mainitsin, että hylkäsimme yhden mahdollisista ratkaisuista suorituskyvyn vuoksi. Canvas-vaihtoehto on melko nopea, mutta kukaan ei sanonut, ettei sitä voisi optimoida vielä enemmän. Aloitetaan siitä, että emme oikeastaan välitä muotojen siirtymisestä, kun ne ovat selaimen näkymäalueen ulkopuolella.
On toinenkin selain API, jota ohjelmoijat rakastivat - IntersectionObserver. Sen avulla voimme seurata tiettyjä sivun elementtejä ja käsitellä tapahtumia, jotka käynnistyvät, kun kyseiset elementit ilmestyvät tai katoavat näkymästä. Juuri nyt - meillä on melko helppo tilanne - luodaan näkyvyyden tila, muutetaan sitä IntersectionObserver-tapahtumakäsittelijöiden ansiosta ja yksinkertaisesti kytketään renderöintijärjestelmä päälle/pois tiettyjen muotojen osalta. Ja ... boom, suorituskyky on parantunut paljon! Renderöimme vain ne asiat, jotka ovat näkyvissä näkymäikkunassa.
Yhteenveto
Toteutustavan valitseminen on usein vaikea valinta, varsinkin kun käytettävissä olevilla vaihtoehdoilla näyttää olevan samanlaisia etuja ja haittoja. Avain oikean valinnan tekemiseen on kunkin vaihtoehdon analysoiminen ja niiden poissulkeminen, joita pidämme vähemmän hyödyllisinä. Kaikki ei ole yksiselitteistä - jokin ratkaisu vaatii enemmän aikaa kuin muut, mutta se saattaa olla helpommin optimoitavissa tai paremmin muokattavissa.
Vaikka uusia JS-kirjastoja ilmestyy lähes joka minuutti, on asioita, joita ne eivät pysty ratkaisemaan. Siksi jokaisen front-end-insinöörin (eikä vain heidän) pitäisi tuntea selaimen API:t, pysyä ajan tasalla teknisistä uutisista ja joskus vain miettiä "miltä tämän kirjaston toteutukseni näyttäisi, jos minun pitäisi tehdä tämä?". Kun meillä on enemmän tietoa selaimista, voimme rakentaa todella hienoja asioita, tehdä hyviä päätöksiä käyttämistämme työkaluista ja olla varmempia omasta koodi.
Lue lisää:
– Ruby 3.0. Ruby ja vähemmän tunnetut yksityisyyden valvontamenetelmät
– Turpa kiinni ja ota rahasi #1: Tuotekehitysprosessin piilokustannukset ja todellinen ketteryys
– CTO:n haasteet - ohjelmistotuotteiden skaalautuminen ja kasvu