W sumie ciekawe case study z #webdev #programowanie

Zwykle się nie zdarza w 2024. Ale musiałem zaimplementować obrazki na spritach jak 20 lat temu.

Problem
Mapka z polskimi herbami https://deykun.github.io/maps/heraldyka

Herbów było 2k, każdy na absolucie każdy był w osobnym src, jak się wchodziło (o dziwo na chromie o wiele gorzej niż na firefoxie) to była zawiecha na ileś sekund (potem jak się ogarnęło to już raczej działało), raport z lighthouse 3/4 się psuł przy odpaleniu i renderował się dobre 3 minuty+ (zawierał uwagi o przesunięciach w tych setkach elementów).

Dostałem nawet 2 razy bana na IP na githubie, bo 3 otwarte karty potrafiły pobrać 8k obrazków. Wspomniane tutaj.

Raport z lighthouse jest we wpisie.
18.8 sekund blokowania wątku!

Ale w sumie ciekawy kejs, bo chcemy mieć elementy w x i y i chcemy mieć to 2k obrazków.

Oczywiste nieoczywiste rozwiązania to:

  • przenieść mapkę do canvasa pozbędziemy się wtedy 2k nodów html
  • stworzyć sprite obrazków i kadrować

Co zrobiłem:

  1. Zmieniłem obrazki na webp, dodałem srcset, co poprawiło wynik delikatnie
  2. Stworzyłem canvasa (ostatecznie go nie używam na tej stronie)
  3. Do canvasa stworzyłem sprite 180 herbów na obrazek -> zamiast 2000 obrazków, pobiera ~11
  4. Wykorzystałem spritery na tej stronie bez canvasa (jako background-image)

Rezultat:
Strona się ładuje normalnie, skok z 52/100 punktów wydajności przy 2.1k herbów do 81/100 z 2.6k herbów.

Issue na githubie: https://github.com/Deykun/maps/issues/16

W sumie spoko przypadek, pierwszy raz używałem spritów i canvasa dla zwykłej i koniecznej optymalizacji.
e9181fbd-d0e0-4741-b735-eda425da0eb9
24dc7a57-1f36-45ae-8b5f-7b7bc126a79d
dotevo

no ale css też obsługuje sprite, więc dałoby radę tego użyć

wombatDaiquiri

@Deykun a myślałeś o użyciu "spritesheeta" i przycięciu do odpowiedniego herbu w HTMLu?

Deykun

@wombatDaiquiri

a myślałeś o użyciu "spritesheeta" i przycięciu do odpowiedniego herbu w HTMLu?

No o tym jest wpis, że tego użyłem chyba. ;D


Przykłady:

https://deykun.github.io/maps/images/heraldry/pl/web/sprites/gminy-0.webp

https://deykun.github.io/maps/images/heraldry/pl/web/sprites/gminy-1.webp

wombatDaiquiri

@Deykun przyznaję że przeczytałem po łebkach xD skąd limit 180 herbów?

Deykun

@wombatDaiquiri

Paczka którą kleiłem obrazki robi domyślnie je jeden pod drugim, jakbym chciał grid to bym musiał jakąś pętle zrobić i kleić wiersze i kolumny (może kiedyś zrobię). Ale tak prosto bo y = index * wysokość herbu + index * odstęp i działa.


Przy 200 herbów na obrazek paczka do obrazków rzucała błędem, że wysokość 16000px to za dużo żeby zapisać webp.

Neverius

@Deykun to o czym piszesz to właśnie spritesheet albo image/texture atlas.

Możesz to sobie wygenerować przy pomocy różnorakiego softu/paczek z neta (pewnie masz jakąś gównianą paczkę że nie ogarnia bin/grid packingu oraz generowania indexów/offsetów do tego, ale nie ocenię bo JS-a nie tykam).


Osobiście wykorzystałbym texture packer z libGDX ( tutaj masz GUI do tego bo można też tego stand-alone używać jeśli nie ogarniasz Java czy tam używanie tego z terminala i ręczne konfigurowanie to za dużo zachodu).


Ja tego używałem z poziomu Java do generowania na żywo przy odpalaniu gierki atlasów składających się z tysięcy obrazków z zamkniętego formatu zanim to pchałem do GPU. LibGDX używa spoko bin packera do upychania obrazków, ale jeśli z jakiegoś powodu potrzebujesz mieć grid to jest tam taka opcja.

Deykun

Rozwiązanie z canvasem wykorzystuję dla mapki Europy gdzie wszystkie kraję będę renderować (obecnie z 3 mam 4.2k herbów).

https://deykun.github.io/maps/heraldry


Ale ta strona ma jeszcze swoje własne bolączki jeszcze (niezwiązane z ładowaniem).

Zaloguj się aby komentować