Komponent IntersectionObservers informuje, gdy obserwowany element pojawia się w widocznym obszarze przeglądarki lub go opuszcza.
Załóżmy, że chcesz śledzić, kiedy element w modelu DOM pojawia się w widocznym widocznym obszarze. Warto to zrobić, aby w odpowiednim momencie ładować obrazy z leniwego ładowania lub aby wiedzieć, czy użytkownik faktycznie widzi określony baner reklamowy. Aby to zrobić, połącz zdarzenie przewijania lub użyj okresowego licznika czasu i wywołaj getBoundingClientRect()
dla tego elementu.
To podejście jest jednak powolne, ponieważ każde wywołanie metody getBoundingClientRect()
wymusza na przeglądarce przekładanie całej strony i wprowadza w witrynie spore zacięcie. Sprawy stają się niemal niemożliwe, gdy wiesz, że witryna jest wczytywana w elemencie iframe, a chcesz wiedzieć, kiedy użytkownik widzi dany element. Pojedynczy model źródłowy i przeglądarka nie pozwalają na dostęp do żadnych danych ze strony internetowej zawierającej element iframe. Jest to typowy problem np. w przypadku reklam, które są często ładowane za pomocą elementów iframe.
Do czego stworzyliśmy narzędzie IntersectionObserver
, aby zwiększyć efektywność testu widoczności. Teraz działa on we wszystkich nowoczesnych przeglądarkach. IntersectionObserver
informuje, kiedy obserwowany element pojawia się w widocznym obszarze przeglądarki lub kiedy z niego wychodzi.
Jak utworzyć IntersectionObserver
Interfejs API jest dosyć mały i najlepiej go opisać na 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 domyślnych opcji IntersectionObserver
wywołanie zwrotne będzie wywoływane zarówno wtedy, gdy element wyświetla się częściowo, jak i gdy całkowicie opuści widoczny obszar.
Jeśli musisz obserwować wiele elementów, możesz to robić. Zalecamy obserwowanie wielu elementów przy użyciu tego samego wystąpienia IntersectionObserver
, wywołując metodę observe()
wielokrotnie.
Parametr entries
jest przekazywany do wywołania zwrotnego, które jest tablicą obiektów IntersectionObserverEntry
. Każdy taki obiekt zawiera zaktualizowane dane skrzyżowań jednego z zaobserwowanych 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
// ...
Wynik rootBounds
jest wynikiem wywołania metody getBoundingClientRect()
w elemencie głównym, który jest domyślnie widocznym obszarem. boundingClientRect
jest wynikiem wywołania funkcji getBoundingClientRect()
w obserwowanym elemencie. intersectionRect
to przecięcie tych 2 prostokątów i w praktyce wskazuje, którą część zaobserwowanego elementu jest widoczna. intersectionRatio
jest blisko ze sobą powiązany i informuje, jaka część elementu jest widoczna. Dysponując tymi informacjami, możesz teraz wdrożyć takie funkcje, jak automatyczne wczytywanie zasobów, zanim pojawią się one na ekranie. Wydajnie.
Sieci IntersectionObserver
dostarczają dane asynchronicznie, a kod wywołania zwrotnego jest uruchamiany w wątku głównym. Dodatkowo specyfikacja wskazuje, że implementacje IntersectionObserver
powinny używać tagu requestIdleCallback()
. Oznacza to, że wywołanie podanego wywołania zwrotnego ma niski priorytet i zostanie wykonane przez przeglądarkę w czasie bezczynności. To świadoma decyzja dotycząca projektu.
Przewijane elementy div
Nie przepadam za przewijaniem treści w elemencie, ale nie chcę tu niczego oceniać, podobnie jak IntersectionObserver
. Obiekt options
przyjmuje opcję root
, która umożliwia zdefiniowanie jako poziomu głównego alternatywy dla widocznego obszaru. Pamiętaj, że element root
musi być elementem nadrzędnym wszystkich obserwowanych elementów.
Połącz te elementy.
Nie! Niegrzeczny programista. Nie jest to świadome wykorzystanie cykli procesora przez użytkownika. Weźmy na przykład nieskończone przewijanie. W takiej sytuacji zdecydowanie zalecamy dodanie do DOM wartowników i ich obserwację (i ich recykling). Pamiętaj, by dodać czujnik blisko ostatniego elementu w przewijaniu nieskończonym. Gdy pojawi się komunikat, możesz użyć wywołania zwrotnego, by wczytać dane, utworzyć następne elementy, dołączyć je do DOM i odpowiednio zmienić pozycję nadawcy. Jeśli prawidłowo poddasz recykling, nie jest wymagane żadne dodatkowe wywołanie metody observe()
. IntersectionObserver
działa dalej.
Prosimy o więcej informacji
Jak już wspomnieliśmy, wywołanie zwrotne będzie się uruchamiać raz, gdy obserwowany element znajdzie się częściowo w widocznym obszarze, a drugi raz, gdy znajdzie się on poza widocznym obszarem. Dzięki temu IntersectionObserver
uzyskasz odpowiedź na pytanie „Czy element X jest widoczny?”. W niektórych przypadkach może to jednak nie wystarczyć.
W tym celu warto skorzystać z opcji threshold
. Pozwala zdefiniować tablicę progów intersectionRatio
. Wywołanie zwrotne będzie wykonywane za każdym razem, gdy intersectionRatio
przekroczy jedną z tych wartości. Domyślna wartość dla threshold
to [0]
, która objaśnia domyślne działanie. Jeśli zmienimy threshold
na [0, 0.25, 0.5, 0.75, 1]
, będziemy otrzymywać powiadomienie za każdym razem, gdy pojawi się dodatkowa ćwierć elementu:
Czy są jakieś inne opcje?
Obecnie oprócz powyższych opcji jest dostępnych tylko 1 dodatkowa opcja. rootMargin
umożliwia określanie marginesów elementu głównego, dzięki czemu można zwiększać lub zmniejszać obszar używany na skrzyżowaniach. Marginesy te są określane za pomocą ciągu znaków w stylu CSS á la "10px 20px 30px 40px"
, określającego odpowiednio górny, prawy, dolny i lewy margines. Podsumowując, struktura opcji IntersectionObserver
obejmuje 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],
});
Magia <iframe>
Elementy IntersectionObserver
zostały zaprojektowane specjalnie z myślą o usługach reklamowych i widżetach sieci społecznościowych, które często korzystają z elementów <iframe>
i mogą być przydatne, jeśli wiadomo, czy są widoczne. Jeśli <iframe>
wykryje jeden z jego elementów, zarówno przewinięcie elementu <iframe>
, jak i przewinięcie okna zawierającego element <iframe>
spowoduje wywołanie zwrotne w odpowiednich momentach. W drugim przypadku zasada rootBounds
ma jednak wartość null
, aby uniknąć wycieku danych między źródłami.
Czego IntersectionObserver
nie dotyczy?
Pamiętaj, że IntersectionObserver
nie celowo nie ma idealnych pikseli ani nie ma małego opóźnienia. Korzystanie z nich w takich zadaniach jak animacje zależne od przewijania z pewnym prawdopodobieństwem zakończy się niepowodzeniem, ponieważ dane staną się nieaktualne w chwili ich użycia. Wyjaśnienie zawiera więcej informacji o pierwotnych przypadkach użycia właściwości IntersectionObserver
.
Ile mogę jeszcze zrobić w trakcie oddzwonienia?
Short 'n Sweet: zbyt wiele czasu na oddzwonienie spowoduje opóźnienie aplikacji – obowiązują wszystkie typowe metody.
Idźcie dalej i przecinajcie swoje elementy
Przeglądarka IntersectionObserver
jest dobrze obsługiwana, ponieważ działa we wszystkich nowoczesnych przeglądarkach. W razie potrzeby można użyć kodu polyfill w starszych przeglądarkach. Znajdziesz go w repozytorium WICG. Oczywiście nie przyniesie to korzyści związanych z wydajnością, które zapewnia implementacja kodu polyfill.
Możesz już zacząć korzystać z IntersectionObserver
. Powiedz nam, jaki był pomysł.