Zbliżamy się do IntersectionObserver

IntersectionObserver informuje, kiedy obserwowany element wchodzi do widocznego obszaru przeglądarki lub z niego wychodzi.

Obsługa przeglądarek

  • Chrome: 51.
  • Edge: 15.
  • Firefox: 55.
  • Safari: 12.1.

Źródło

Załóżmy, że chcesz śledzić, kiedy element DOM trafia do widocznego widocznego obszaru. Możesz to zrobić, aby ładować obrazy z opóźnieniem w odpowiednim momencie lub dlatego, że chcesz wiedzieć, czy użytkownik faktycznie patrzy na dany baner reklamowy. Możesz to zrobić, podłączając zdarzenie przewijania lub używając okresowego timera i wywołania getBoundingClientRect() w tym elemencie.

To rozwiązanie działa jednak wolniej, ponieważ każde wywołanie metody getBoundingClientRect() wymusza na przeglądarce przekształcenie całej strony, co powoduje znaczny zatłóczenie witryny. Gdy wiesz, że Twoja witryna jest wczytywana w ramce i chcesz się dowiedzieć, kiedy użytkownik może zobaczyć dany element, sytuacja staje się prawie niemożliwa. Model pojedynczego źródła i przeglądarka nie pozwolą Ci uzyskać dostępu do żadnych danych ze strony internetowej zawierającej element iframe. Jest to częsty problem w przypadku reklam, które są często wczytywane za pomocą ramek osadzonych.

IntersectionObserver został zaprojektowany tak, aby usprawnić ten test widoczności. Jest dostępny we wszystkich nowoczesnych przeglądarkach. IntersectionObserver informuje, kiedy obserwowany element wchodzi do widocznego obszaru przeglądarki lub z niego wychodzi.

Widoczność elementu iframe

Jak utworzyć IntersectionObserver

Interfejs API jest raczej mały i najlepiej opisz go na tym przykładzie:

const io = new IntersectionObserver(entries => {
  console.log(entries);
}, {
  /* Using default options. Details below */
});

// Start observing an element
io.observe(element);

// Stop observing an element
// io.unobserve(element);

// Disable entire IntersectionObserver
// io.disconnect();

W przypadku użycia domyślnych opcji IntersectionObserver wywołanie zwrotne będzie wywoływane zarówno wtedy, gdy element jest częściowo widoczny, jak i gdy całkowicie opuszcza widoczny obszar.

Jeśli musisz obserwować wiele elementów, możesz i powinieneś to robić, używając tego samego wystąpienia IntersectionObserver, wywołując funkcję observe() kilka razy.

Do funkcji wywołania zwrotnego przekazywany jest parametr entries, który jest tablicą obiektów IntersectionObserverEntry. Każdy taki obiekt zawiera zaktualizowane dane dotyczące przecięcia dla jednego z obserwowanych elementów.

🔽[IntersectionObserverEntry]
    time: 3893.92
    🔽rootBounds: ClientRect
        bottom: 920
        height: 1024
        left: 0
        right: 1024
        top: 0
        width: 920
    🔽boundingClientRect: ClientRect
    // ...
    🔽intersectionRect: ClientRect
    // ...
    intersectionRatio: 0.54
    🔽target: div#observee
    // ...

rootBounds to wynik wywołania metody getBoundingClientRect() w elemencie głównym, który domyślnie jest widocznym obszarem. boundingClientRect jest wynikiem wywołania getBoundingClientRect() dla zaobserwowanego elementu. intersectionRect to przecięcie tych 2 prostokątów, które określa, który fragment obserwowanego elementu jest widoczny. Parametr intersectionRatio jest ściśle powiązany z parametrem i pokazuje, jak dużo elementu jest widoczne. Dzięki tym informacjom możesz teraz wdrażać funkcje takie jak wczytywanie komponentów w samym momencie, gdy mają się pojawić na ekranie. wydajnie.

Współczynnik przecięcia.

Reguły IntersectionObserver dostarczają dane asynchronicznie, a kod wywołania zwrotnego jest uruchamiany w wątku głównym. Specyfikacja określa też, że implementacje IntersectionObserver powinny używać requestIdleCallback(). Oznacza to, że połączenie z Twoim numerem będzie miało niski priorytet i będzie wykonywane przez przeglądarkę w czasie bezczynności. Jest to przemyślana decyzja projektowa.

Przewijane elementy div

Nie jestem zwolenniczką przewijania w ramach elementu, ale nie jestem też sędzią, a IntersectionObserver też nie. Obiekt options przyjmuje opcję root, która umożliwia zdefiniowanie alternatywy dla widoku jako elementu skojarzonego. Pamiętaj, że root musi być przodkiem wszystkich obserwowanych elementów.

Łącz wszystkie te elementy.

Nie! Niewłaściwy deweloper To nie jest rozsądne wykorzystanie cykli procesora użytkownika. Weźmy na przykład nieskończony scroller: w takim przypadku zdecydowanie zaleca się dodanie do DOM elementów kontrolnych i obserwowanie ich (oraz ich recykling). Należy dodać element kontrolny w pobliżu ostatniego elementu w nieskończonym scrollerze. Gdy czujnik znajdzie się w polu widzenia, możesz użyć wywołania zwrotnego, aby załadować dane, utworzyć kolejne elementy, dołączyć je do DOM i odpowiednio zmienić położenie czujnika. Jeśli prawidłowo poddasz czujnik recyklingowi, nie musisz dodatkowo kontaktować się z observe(). IntersectionObserver nadal działa.

Nieskończony pasek przewijania

Poproszę o więcej aktualizacji

Jak już wspomnieliśmy, funkcja wywołania zwrotnego zostanie wywołana raz, gdy obserwowany element częściowo znajdzie się w widoku, i jeszcze raz, gdy opuści obszar widoku. Dzięki temu IntersectionObserver uzyska odpowiedź na pytanie „Czy element X jest widoczny?”. W niektórych przypadkach może to jednak nie wystarczyć.

Właśnie wtedy przydaje się opcja threshold. Umożliwia określenie tablicy intersectionRatio progów. Funkcja zwracana po wywołaniu zostanie wywołana za każdym razem, gdy wartość intersectionRatio przekroczy jedną z tych wartości. Wartością domyślną dla threshold jest [0], co wyjaśnia działanie domyślne. Jeśli zmienimy wartość threshold na [0, 0.25, 0.5, 0.75, 1], będziemy otrzymywać powiadomienia za każdym razem, gdy będzie widoczna kolejna ćwiartka elementu:

Animacja progu.

Czy są inne opcje?

Obecnie, oprócz wymienionych powyżej, jest tylko 1 dodatkowa opcja. rootMargin pozwala określić marginesy dla korzenia, co pozwala zwiększać lub zmniejszać obszar używany do skrzyżowań. Te marginesy są określone za pomocą ciągu znaków w stylu CSS (à la "10px 20px 30px 40px"), który określa odpowiednio marginesy górny, prawy, dolny i lewy. Podsumowując, struktura opcji IntersectionObserver oferuje te opcje:

new IntersectionObserver(entries => {/* … */}, {
  // The root to use for intersection.
  // If not provided, use the top-level document's viewport.
  root: null,
  // Same as margin, can be 1, 2, 3 or 4 components, possibly negative lengths.
  // If an explicit root element is specified, components may be percentages of the
  // root element size.  If no explicit root element is specified, using a
  // percentage is an error.
  rootMargin: "0px",
  // Threshold(s) at which to trigger callback, specified as a ratio, or list of
  // ratios, of (visible area / total area) of the observed element (hence all
  // entries must be in the range [0, 1]).  Callback will be invoked when the
  // visible ratio of the observed element crosses a threshold in the list.
  threshold: [0],
});

<iframe> magiczny

Cele IntersectionObserver zostały zaprojektowane z myślą o usługach reklamowych i widżetach sieci społecznościowych, które często używają elementów <iframe> i mogą skorzystać z informacji o ich widoczności. Jeśli <iframe> wykryje jeden z jego elementów, zarówno przewijanie elementu <iframe>, jak i przewinięcie okna zawierającego <iframe> spowoduje wywołanie zwrotne w odpowiednim momencie. W tym drugim przypadku wartość parametru rootBounds zostanie ustawiona na null, aby uniknąć wycieku danych z różnych źródeł.

O czym nie jest IntersectionObserver

Pamiętaj, że IntersectionObserver nie jest celowo ani idealnie dokładny, ani o niskiej latencji. Korzystanie z nich w celach takich jak animacje zależne od przewijania kończy się niepowodzeniem, ponieważ w chwili, w której będziesz ich używać, dane staną się nieaktualne. Więcej informacji o pierwotnych przypadkach użycia funkcji IntersectionObserver znajdziesz w tym artykule.

Ile pracy mogę wykonać w ramach wywołania zwrotnego?

Krótko i na temat: zbyt długi czas wywołania funkcji callback spowoduje opóźnienie aplikacji – obowiązują wszystkie standardowe zasady.

Idźcie i przenikajcie elementy

IntersectionObserver jest dobrze obsługiwany przez przeglądarki, ponieważ jest dostępny we wszystkich nowoczesnych przeglądarkach. W starszych przeglądarkach można użyć polyfilla, który jest dostępny w repozytorium WICG. Oczywiście nie uzyskasz korzyści związanych z wydajnością, jakie daje implementacja natywne.

Możesz zacząć korzystać z IntersectionObserver już teraz. Powiedz nam, co udało Ci się znaleźć.