W programowaniu dla potrzeb Internetu lub szeroko pojętej dyscyplinie tworzenia stron, czasem można natknąć się na z pozoru łatwe problemy, które są zaskakująco trudne do rozwiązania. Do niedawna jednym z takich problemów było wykrycie czy dany element jest widoczny w polu roboczym przeglądarki.

Istnieje wiele przypadków, w których chcielibyśmy jako programiści widzieć (i na bieżąco wykrywać) czy przy scrollowaniu przez użytkownika strony internetowej dany obiekt znajduje się w zasięgu viewportu czy jeszcze nie. Do niedawna każdy kto w jakikolwiek sposób wykonywał interaktywne animacje lub optymalizował stronę, wykorzystywał do tego celu: zdarzenie scroll, proste operacje matematyczne na takich wartościach jak window.pageYOffset czy getBoundingClientRect().top i prosty throttling…

Tego typu rozwiązania przez wiele lat jakoś działały ale negatywnie wpływały na wydajność strony i nie były nigdy w stu procentach niezawodne. Alternatywą do kodowania własnych rozwiązań były biblioteki np. Hunt.js lub wtyczki do jQuery np. Visible.js lub IsInViewport.js. Nie muszę chyba tłumaczyć jakie wady ma wykorzystanie biblioteki jQuery i wtyczki do tak prostej rzeczy. Na szczęście twórcy przeglądarek wprowadzili rozwiązanie, które znacznie ułatwia śledzenie pozycji elementu DOM względem viewportu przeglądarki – jest nim Intersection Observer API.

Co to jest Intersection Observer API?

Intersection Observer API to interfejs, który umożliwia asynchroniczną obserwację zmian przecięcia viewportu z wybranym elementem DOM. Może to też być element przecięcia elementu z elementem nadrzędnym.

Tak jak wspomniałem we wstępie, wykrywanie widoczności elementu bywało trudnym zadaniem, w przypadku którego rozwiązania były zawodne i podatne na spadki wydajności strony internetowej. Wraz z rozwojem front-endu rosło zapotrzebowanie na tego rodzaju rozwiązania. Takie wykrywanie czy dany element jest widoczny w polu roboczym przeglądarki jest potrzebny do:

  • opóźnionego ładowania treści podczas przewijania strony (lazy load multimediów, iframe itp.),
  • wdrożenia infinite-scroll,
  • raportowania widoczności reklam,
  • synchronizacji interaktywnych, reagujących na scroll animacji,
  • i innych prac optymalizacyjnych.

Dlaczego dotychczasowe rozwiązania polegające na podłączaniu się do zdarzenia scroll były mało wydajne i zawodne? Zauważ, że wszystkie te sprawdzenia i pętle działają w głównym wątku. Przy wielu takich mechanizmach wydajność strony może być zauważalnie obniżona. Samo użycie zdarzenia scroll może powodować problemy, bo w końcu użytkownik musi przewinąć widok aby funkcja przynajmniej raz wykonała test widoczności.

Rozważmy stronę internetową, która wykorzystuje mechanizm nieskończonego przewijania (infinite-scroll) oraz optymalizację lazy-load korzystającą z tradycyjnego rozwiązania JavaScript. Załóżmy, że ta sama strona wykorzystuje też bibliotekę dostarczoną przez dostawcę reklam oraz bibliotekę do wykonywania prostych animacji, np. Anime.js lub GSAP. Każdy z tych mechanizmów ma własne procedury wykrywania skrzyżowań i wszystkie działające w głównym wątku. Gdy użytkownik przewija stronę, te procedury wykrywania skrzyżowań są stale uruchamiane podczas przewijania, co powoduje, że w skrajnych przypadkach taka strona może się zacinać co znacznie obniży user experience takiej strony internetowej.

Intersection Observer API pozwala stworzyć funkcję zwrotną (ang. callback), który jest wykonywany wtedy, kiedy dwa elementy się przetną bądź wybrany element przetnie się z viewportem przeglądarki.

Jak działa Intersection Observer API

Dzięki temu, przeglądarka nie musi robić dodatkowych testów podłączając się do zdarzenia scroll w głównym wątku. Ponieważ Intersection Observer API jest natywną funkcją przeglądarek, to autorzy stron internetowych nie muszą optymalizować ani opóźniać tego mechanizmu – tak jak było w przypadku wspomnianego throttlingu. Przeglądarka może od teraz dowolnie optymalizować i zarządzać skrzyżowaniami według własnego uznania.

Przykłady wykorzystania Intersection Observer API

Pewnie każdy z nas widział na stronie liczniki, które zwiększają się od zera do konkretnej liczby. Aby efekt był widoczny programista musi wykryć moment, w którym użytkownik przewinie stronę do takiego momentu że liczniki i animacja zwiększania wartości będzie widoczna na ekranie użytkownika. Zakładając, że liczniki są uruchamiane funkcją licznikiStart() i znajdują się w elemencie div z klasą liczniki kod odpowiedzialny za uruchomienie animacji będzie wyglądał tak:

function handleIntersection(entries) {
   entries.map((entry) => {
     if (entry.isIntersecting) {
         licznikiStart();
         observer.unobserve(entry.target);
     }
   });
 }
 const liczniki = document.querySelectorAll('.liczniki');
 const observer = new IntersectionObserver(handleIntersection);
 liczniki.forEach(num => observer.observe(num));  

Podobnie będzie wyglądał kod wykorzystania Intersection Observer API w przypadku innych animacji, które mają zareagować na pojawienie się użytkownikowi w przeglądarce.

W dokumentacji JavaScript, którą podlinkowałem w źródłach można znaleźć przykład ilustrujący działanie Intersection Observer API za pomocą kolorowanego diva. Kilka ciekawych przykładów można znaleźć w drugim podlinkowanym wpisie.

Wsparcie Intersection Observer API ze strony przeglądarek

Intersection Observer API to stosunkowo nowość i nie jest wspierana we wszystkich przeglądarkach. Biorąc jednak pod uwagę szerokie wsparcie i zalety korzystania z Intersection Observer API warto od dziś stosować to rozwiązanie w nowopowstałych stronach i aplikacjach internetowych.

Obsługa Intersection Observer API w przeglądarkach, źródło: https://caniuse.com

Źródła

Oceń artykuł na temat: Intersection Observer API – widoczność elementów DOM
Średnia : 4.8 , Maksymalnie : 5 , Głosów : 9