Animuoti aukštį - teisingas būdas

Būkime atviri. Animuoti ūgį gali būti didžiulis skausmas. Man tai buvo nuolatinė kova tarp noro turėti gražių animacijų ir nenoro mokėti milžiniškų spektaklio išlaidų, susijusių su animaciniu ūgiu. Dabar - viskas padaryta.

Viskas prasidėjo, kai dirbau prie savo šalutinio projekto - gyvenimo aprašymo kūrėjo, kuriame galite bendrinti nuorodas į savo gyvenimo aprašymą, kurios yra aktyvios tik tam tikrą laiką.

Norėjau turėti gražią animaciją visoms gyvenimo aprašymo sekcijoms ir sukūriau reakcijos komponentą, kuris atliko animaciją. Tačiau netrukus atradau, kad šis komponentas visiškai sugadino našumą žemesnės klasės įrenginiuose ir kai kuriose naršyklėse. Po velnių, net mano aukščiausios klasės „Macbook“ profesionalas stengėsi išlaikyti sklandų animacijos kadrų per sekundę greitį.

To priežastis, be abejo, yra tai, kad animuojant aukščio ypatybę CSS, naršyklė atlieka brangias kiekvieno kadro išdėstymo ir dažymo operacijas. „Google Web Fundamentals“ yra fantastiškas skyrius apie našumo perteikimą, siūlau tai patikrinti.

Trumpai, nors - kai pakeisite CSS geometrinę ypatybę, naršyklė turi koreguoti ir atlikti skaičiavimus, kaip šis pakeitimas paveikia puslapio maketą, tada ji turės iš naujo pateikti puslapį atlikdama veiksmą, vadinamą dažais.

Kodėl mums netgi turėtų rūpėti spektaklis?

Gali būti pagunda nepaisyti pasirodymo. Tai nėra išmintinga, tačiau gali būti viliojanti. Žvelgiant iš verslo perspektyvos, jūs sutaupote daug laiko, kurį kitu atveju galite praleisti kurdami naujas funkcijas.

Tačiau našumas gali tiesiogiai paveikti jūsų apatinę eilutę. Kuo naudinga sukurti daugybę funkcijų, jei jų niekas nenaudoja? Keli „Amazon“ ir „Google“ atlikti tyrimai rodo, kad tai tiesa. Našumas yra tiesiogiai susijęs su programų naudojimu ir apatinėmis pajamomis.

Kita spektaklio pusė yra vienodai svarbi. Mes, kaip kūrėjai, esame atsakingi už tai, kad žiniatinklis išliktų prieinamas visiems - tai darome todėl, kad tai teisinga. Kadangi internetas nėra skirtas tik jums ir man, jis skirtas visiems.

Kaip rodo puikus Addy Osmani straipsnis, žemos klasės įrenginiams reikia gerokai ilgiau analizuoti ir vykdyti „javascript“, palyginti su aukštesnio lygio analogais.

Kad išvengtume klasės skirtumo internete, turime būti nenumaldomi siekdami savo veiklos. Man tai reiškė būti kūrybingam ir rasti kitą būdą, kaip pasiekti savo animaciją, neaukojant spektaklio.

Animuokite aukštį teisingai

Jei jums nerūpi kaip ir tiesiog norite pamatyti tiesioginį pavyzdį, peržiūrėkite toliau pateiktas nuorodas į demonstracinę svetainę, pavyzdžius ir „npm“ paketą, kad galėtumėte reaguoti:

  • Demonstracinė svetainė, naudojant šią techniką
  • Gyvas pavyzdys vanilėje JS
  • Paprastas reagavimo pavyzdys
  • NPM paketas ir reagavimo dokumentai

Aš sau uždaviau klausimą, kaip galėčiau išvengti spektaklio išlaidų, kurios patiriamos animuojant aukštį. Paprastas atsakymas - negalima.

Užtat man reikėjo kūrybiškai naudotis kitomis CSS savybėmis, kurios nepatiria tų išlaidų. Būtent transformuojasi.

Kadangi transformacijos neturi įtakos aukščiui. Mes negalime paprasčiausiai pritaikyti elementui paprastos savybės ir tai padaryti. Turime būti protingesni už tai.

Būdas, kurį naudosime atlikdami aukščio animaciją, iš tikrųjų yra suklastojimas su transformacija: scaleY. Animacija atliekama keliais etapais:

Štai pavyzdys:

 ${this.markup} `
  • Pirmiausia turime gauti pradinį elemento konteinerio aukštį. Tada nustatome, kad išorinis konteinerio aukštis būtų aiškus iki šio aukščio. Dėl to bet koks besikeičiantis turinys perpildys sudėtinį rodinį, o išplės jo tėvą.
  • Išorinio konteinerio viduje turime dar vieną div, kuris yra absoliučiai išdėstytas taip, kad apimtų visą divo plotį ir aukštį. Tai yra mūsų fonas ir jis bus keičiamas, kai pakeisime transformaciją.
  • Mes taip pat turime vidinį konteinerį. Vidiniame inde yra žymėjimas ir jis pakeis jo aukštį pagal jame esantį turinį.
  • Štai gudrybė:  Kai pakeisime įvykį, kuris pakeis žymėjimą, imsime naują vidinio konteinerio aukštį ir apskaičiuosime sumą, kurios fonas turi keisti, kad būtų galima pritaikyti naują aukštį. Tada nustatėme foną į skalęY pagal naują sumą.
  • Vaniliniu „javascript“ tai reiškia tam tikrą gudrybę su dvigubu atvaizdavimu. Kartą, kad gautumėte vidinio konteinerio aukštį, kad apskaičiuotumėte skalę. Tada vėl pritaikykite skalę foniniam div, kad jis atliktų transformaciją.

Gyvą pavyzdį galite pamatyti čia, vanilėje JS.

Šiuo metu mūsų fonas buvo tinkamai pakeistas, kad būtų sukurta aukščio iliuzija. Bet kaip su aplinkiniu turiniu? Kadangi mes nebekoreguojame išdėstymo, pakeitimai netrukdo aplinkiniam turiniui.

Kad aplinkinis turinys judėtų. Turime pakoreguoti turinį naudodami transformY. Apgaulė yra paimti turinio išplėstą sumą ir naudoti ją aplinkiniam turiniui perkelti su transformacijomis. Žr. Aukščiau pateiktą pavyzdį.

Animacinis aukštis „React

Kaip jau minėjau anksčiau, šį metodą sukūriau dirbdamas asmeninį projektą „React“. Šioje demonstracinėje svetainėje šis metodas naudojamas tik visoje „aukščio animacijoje“. Peržiūrėkite demonstracinę svetainę čia.

Sėkmingai tai įgyvendinęs, skyriau laiko pridėti šį komponentą ir keletą papildomų komponentų į mažą animacijos biblioteką, kurią sukūriau „React“. Jei jus domina, atitinkamą informaciją galite rasti čia:

  • čia galite peržiūrėti NPM biblioteką
  • Dokumentaciją galite rasti čia.

Svarbiausi šios bibliotekos komponentai yra „AnimateHeight“ ir „AnimateHeightContainer“. Panagrinėkime juos:

// Inside a React component // handleAnimateHeight is called inside AnimateHeight and is passed the // transitionAmount and optionally selectedId if you pass that as a prop to // AnimateHeight. This means that you can use the transitionAmount to // transition your surrounding content.const handleAnimateHeight = (transitionAmount, selectedId) => { this.setState({ transitionAmount, selectedId }); }; // Takes a style prop, a shouldchange prop and a callback. shouldChange // determines when the AnimateHeight component should trigger, which is // whenever the prop changes. The same prop is used to control which // content to show.  {this.state.open && } {!this.state.open && } 
  • Pavyzdys su judančiu aplinkiniu turiniu

Ankstesniuose pavyzdžiuose parodyta, kaip naudoti „AnimateHeight“ ir rankiniu būdu suaktyvinti aplinkinį turinį, kad prisitaikytumėte. Bet ką daryti, jei turite daug turinio ir nenorite šio proceso atlikti rankiniu būdu? Tokiu atveju galite naudoti „AnimateHeight“ kartu su „AnimateHeightContainer“.

Norėdami naudoti „AnimateHeightContainer“, turite pateikti visiems aukščiausio lygio vaikams atramą, vadinamą „animateHeightId“, kurią taip pat reikia perduoti jūsų „AnimateHeight“ komponentams:

// Inside React Component const handleAnimateHeight = (transitionAmount, selectedId) => { this.setState({ transitionAmount, selectedId }); }; // AnimateHeight receives the transitionAmount and the active id of the AnimateHeight that fired. {this.state.open &&  {!this.state.open && }  // When AnimateHeight is triggered by state change // this content will move because the animateHeightId // is greater than the id of the AnimateHeight component above I will move I will also move 

Kaip matote iš šio pavyzdžio, „AnimateHeight“ gauna informaciją, kurios reikia norint pakoreguoti turinį, kai „AnimateHeight“ komponentas suveikia keičiant būseną.

Kai tai atsitiks, „AnimateHeight“ komponentas suaktyvins atgalinį skambutį ir nustatys savybes būsenoje. „Inside AnimateHeight“ atrodo maždaug taip (supaprastinta):

// Inside AnimateHeight componentDidUpdate() { if (update) { doUpdate() callback(transitionAmount, this.props.animateHeightId) } } // Equivalent to calling this function: const handleAnimateHeight = (transitionAmount, selectedId) => { this.setState({ transitionAmount, selectedId }); }; handleAnimateHeight(transitionAmount, this.props.animateHeight)

Dabar jūs nurodote sumą, kurią turinys perkėlė pikseliais, ir suaktyvinto „AnimateHeight“ komponento ID. Kai šias vertes perduosite „AnimateHeightContainer“, jos paims jas ir perves kitus komponentus savyje, su sąlyga, kad aukščiausio lygio vaikams nustatysite didėjančią „animateHeightIds“.

Pažangesni pavyzdžiai:

  • Aplinkinio turinio perkėlimas naudojant „AnimateHeightContainer“
  • Akordeono pavyzdys

PASTABA: Jei naudojate šį metodą, kad animuotumėte aukštį ir perkeltumėte aplinkinį turinį, prie puslapio aukščio turite pridėti perėjimo sumą.

Išvada

Galbūt pastebėjote šiame straipsnyje, kad mes iš tikrųjų neanimizuojame aukščio ir vadiname jį neteisingu. Jūs, žinoma, visiškai teisus. Tačiau aš tvirtai tikiu, kad tai, ką mes vadiname, nėra svarbu. Svarbu tai, kad mes pasiekiame norimą efektą su kuo mažesnėmis sąnaudomis.

Nors manau, kad radau būdą, kuris yra geresnis, nei tiesiogiai animuoti aukščio ypatybes, netvirtinu, kad sugalvojau ar kitaip pagalvojau apie tai, kas dar nebuvo atrasta. Taip pat nevertinu. Galbūt jūsų scenarijuje jums tinka animacinis aukštis - jokių problemų.

Viskas, ko noriu, yra įgalinti ir supaprastinti efektus, kuriuos turime padaryti visi, tačiau kartais patiriame sunkiai padengiamų išlaidų. Bent jau noriu sukelti diskusiją, kurią verta surengti. Kaip galime pagerinti internetą visiems?