Potyczki na froncie, odcinek 1: ScrollObserver


W ramach unowocześniania aplikacji internetowych, poprawy ich interaktywności, dbania o ogólnie pojęte user experience coraz częściej pojawia się potrzeba odpowiedniego reagowania na działania użytkownika, takie jak przewijanie strony. Pożądaną reakcją aplikacji może być wczytywanie kolejnych treści w momencie zbliżenia się do końca strony, ładowanie obrazków na zasadzie lazy loading lub modyfikacja wyświetlanych treści po przewinięciu strony o określoną wielkość.

Z powyższymi zagadnieniami możemy poradzić sobie w Angularze na co najmniej dwa sposoby. Poniżej opiszę pierwszy z nich, klasyczne rozwiązanie oparte o ScrollEvent.

ScrollEvent

Z eventu Scroll możemy skorzystać w prosty sposób, aby po każdym przewinięciu strony sprawdzać, o ile pikseli strona jest przewinięta w dół.

Aby zapewnić kompatybilność z wszystkimi przeglądarkami, warto użyć kilku sposobów określania położenia strony:

Dodatkowo warto odwoływać się do eventu za pośrednictwem observable, aby skorzystać z operatorów RxJs:

Powyższa funkcja observable najpierw zwraca aktualną pozycję strony, a następnie emituje nową każdorazowo po odebraniu eventu Scroll. Tak przygotowany obiekt może posłużyć jako rdzeń mechanizmu notyfikującego o zmieniającym się wskutek przewijania strony stopniu widoczności wybranych elementów HTML.

Śledzenie widoczności

W jaki zatem sposób śledzić widoczność elementów na podstawie eventu Scroll? W tym celu możemy posłużyć się wcześniej stworzoną observable i podłączyć do niej operator RxJS wykrywający zmianę widoczności. Taki kod mógłby wyglądać następująco:

Powyższy kod zapewni nam notyfkację zawsze wtedy, gdy po przewinięciu strony przez użytkownika obliczona  metodą isItemVisible widoczność elementu el zmieni swoją wartość. Pozostaje tylko zdefiniowanie owej metody.

Wyliczanie widoczności elementu HTML

Aby wyznaczyć widoczność elementu w zależności od aktualnej pozycji scrolla, potrzebne są nam oczywiście informacje o pozycji scrolla, a także kilka innych parametrów:
– wysokość okna przeglądarki w pikselach,
– offset obserwowanego elementu, tzn. położenie jego szczytu względem początku strony,
– wysokość obserwowanego elementu.

Wartości powyższych trzech parametrów wyznaczam następująco:

Na podstawie tych parametrów możemy wyliczyć, o ile pikseli widoczność obserwowanego elementu jest ograniczona od góry i od dołu:

W tym momencie możemy już łatwo wyliczyć, czy element jest chociaż częściowo widoczny, odejmując wyliczone wyżej liczby od całkowitej wysokości elementu:

Na tym etapie dysponujemy obiektem Observable, który możemy zasubskrybować, aby obserwować widoczność elementu przy przewijaniu strony. Istnieje jednak prostsze i bardziej zgodne z filozofią Angulara podejście, z wykorzystaniem dyrektywy.

ScrollObserver w dyrektywie

Dysponując obiektem observable, możemy stworzyć prostą dyrektywę, która w odpowiednim momencie zasubskrybuje go i – co równie ważne – również w odpowiednim momencie zakończy subskrybcję, aby nie dopuścić do wycieków pamięci.

Wystarczy przypięcie powyższej dyrektywy do obserwowanego elementu, aby nasza metoda onScroll(visible: boolean) otrzymywała notyfikacje o zmianie jego widoczności.

Kod i npm

Powyższy kod jest dostępny na Githubie pod adresem:

https://github.com/piotr-zysk/LabIntersectionObserver/tree/master/projects/pz-scroll-observer

Dodatkowo można pobrać go w postaci pakietu npm, aby wykorzystać go w swojej aplikacji

Podsumowanie

Przedstawione rozwiązanie umożliwia monitorowanie zmian widoczności wybranego elementu na stronie internetowej na skutek przewijania strony przez użytkownika. Jest kompatybilne z wszystkimi popularnymi przeglądarkami, również tymi starszymi, takimi jak Internet Explorer. Nie jest to jednak rozwiązanie idealne, przede wszystkim dlatego, że notyfikacje o zmianie widoczności są wysyłane wyłącznie po wystąpieniu eventu przewijania strony. Inne zdarzenia mogące wpłynąć na widoczność elementu, takie jak zmiana wielkości okna przeglądarki lub zmiana treści na stronie, są ignorowane.

Zazwyczaj możemy potrzebować notyfikacji o zmianie widoczności niezależnie od powodu takiej zmiany. W takiej sytuacji powyższe rozwiązanie wymagałoby znacznej rozbudowy i wprowadzania ogromnych dodatkowych komplikacji do już teraz nieco skomplikowanej logiki. To nie brzmi zbyt dobrze, ale na szczęście istnieje inne, dużo prostsze i lepsze wyjście, IntersectionObserver, o którym opowiem w kolejnym odcinku


Piotr Zyśk

O Piotr Zyśk

Od 2019 roku jako programista fullstack w Atenie zgłębiam głównie technologie .Net i Angular. Wcześniej przez kilkanaście lat zajmowałem się szeroko pojętym wsparciem administracyjno-programistycznym w dla dużej sieci call-center. W wolnym czasie lubię wykorzystywać swój komputer na różne sposoby, np. jako studio do tworzenia muzyki lub urządzenie do symulacji rajdów i wyścigów samochodowych. Często również można spotkać mnie w podolsztyńskich lasach na rowerze, z aparatem fotograficznym.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *