Fejlmeldingen
“På mobil hakker skaleringen af KODEkid-logoet hen mod slutningen af scrollingen.”
Det var hele fejlmeldingen. Ingen stack trace, ingen egentlige reproduktionstrin ud over “scroll på en telefon”.
Fristelsen ved sådan en fejl er at begynde at justere easing-kurver og timing — sende en rettelse ud, konstatere at det føles lidt bedre og stadig ikke vide, om problemet faktisk er løst.
Mål, før du ændrer noget
Animationen skalerer syv bogstaver ud fra deres egne centre, indtil de dækker skærmen. Herefter lægges en massiv farveflade over og lukker mellemrummene.
På en telefon med en bredde på 390 px toppede bogstaverne ved 16,5× skalering — hvilket betød, at hvert bogstav blev rasteriseret i en boks på 776 × 1238 CSS-pixels.
Det tal siger ikke så meget i sig selv. Gang det med den device pixel ratio, som telefoner rent faktisk bruger:
776 × 1238 × 3² (DPR 3) ≈ 8,6 millioner pixels — pr. bogstav, gange syv
Det betyder, at browseren rasteriserede omkring 60 millioner pixels af bogstavets kontur på hvert eneste scrub-frame.
Og det skete for en animationstilstand, der — fordi en massiv farveflade samtidig fader ind over skærmen — allerede var usynlig, da det skete.
Alt det GPU-arbejde blev altså brugt på at tegne noget, ingen kunne se.
Hvorfor det ikke nødvendigvis kan ses med DevTools CPU-throttling
Chrome DevTools' CPU-throttling sænker hastigheden på JavaScript-eksekveringen på main thread.
Rasterisering og compositing foregår andre steder — på GPU'en og i en separat proces.
Du kan derfor sænke CPU'en 20× og stadig få et perfekt smooth scroll, fordi flaskehalsen aldrig var JavaScript.
Hvis din testmetode ikke kan reproducere problemet, kan den heller ikke fortælle dig, hvornår du har løst det.
Ved at måle den faktiske pixel-matematik springer man hele den diskussion over.
Løsningen
Når årsagen kan beskrives med et tal, kan løsningen også beskrives med et tal:
Sænk maksimum på små skærme. Den maksimale skalering blev reduceret fra 16,5× til 10× på telefoner — mens desktop, der har rigeligt GPU-overskud, blev efterladt urørt. Det alene giver cirka 2,7× mindre rasteriseringsareal. Fjern elementet fra paint, når det alligevel er usynligt. Når farvefladen er færdig, har bogstaverne samme farve som baggrunden. visibility: hidden på dette tidspunkt ændrer intet visuelt, men fjerner de dyreste frames. Retime animationen, så intet fortsætter med at skalere, efter det allerede er dækket. Den oprindelige timing lod skaleringen fortsætte, efter at farvefladen allerede havde overtaget skærmen — ren spildt arbejde. Verificér det — lad være med bare at sende det live
Rettelsen er først reel, når den er målt på samme måde som problemet.
Det betyder før/efter-målinger af den maksimale skalering og — fordi performance-optimeringer har det med stille og roligt at ødelægge funktionalitet — en fuld test af reverse-scroll.
Når man scroller tilbage op, skal elementet stadig vende præcist tilbage til sin oprindelige tilstand.
En performance-optimering, der efterlader animationen ude af stand til at reversere korrekt, har bare byttet én fejl ud med en anden.
Skrevet af Lars Sohl
