IntersectionObservers informuje o tym, kiedy obserwowany element pojawia się w widocznym obszarze przeglądarki lub go opuszcza.
Załóżmy, że chcesz śledzić, kiedy element DOM trafia do widocznego widocznego obszaru. Może to być przydatne, gdy chcesz leniwie ładować obrazy w odpowiednim momencie lub gdy chcesz wiedzieć, czy użytkownik faktycznie ogląda określony baner reklamowy. Aby to zrobić, podłącz zdarzenie przewijania lub użyj okresowego licznika czasu i wywołaj funkcję getBoundingClientRect()
tego elementu.
To rozwiązanie działa jednak wolniej, ponieważ każde wywołanie metody getBoundingClientRect()
wymusza na przeglądarce przekształcenie całej strony i spowoduje zacinanie się jej zawartości. Sprawy stają się niemal niemożliwe, gdy wiesz, że Twoja witryna wczytuje się w elemencie iframe i chcesz wiedzieć, kiedy użytkownik zobaczy jakiś element. Model pojedynczego punktu początkowego i przeglądarka nie zezwalają na dostęp do żadnych danych ze strony internetowej, która zawiera element iframe. Jest to typowy problem np. w przypadku reklam, które są często ładowane za pomocą elementów iframe.
Zwiększenie wydajności tego testu widoczności IntersectionObserver
opracowaliśmyz myślą we wszystkich nowoczesnych przeglądarkach. IntersectionObserver
informuje, gdy zaobserwowany element pojawia się w widocznym obszarze przeglądarki lub z niego opuszcza.
![Widoczność elementu iframe](https://web.developers.google.cn/static/articles/intersectionobserver/image/iframe-visibility-45640aaa99537.gif?authuser=6&hl=pl)
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 znajdzie się częściowo w widocznym obszarze, jak i gdy całkowicie opuści widoczny obszar.
Jeśli musisz obserwować wiele elementów, jest to możliwe i zaleca się obserwację wielu elementów przy użyciu tego samego wystąpienia IntersectionObserver
przez wielokrotne wywoływanie funkcji observe()
.
Do wywołania zwrotnego przekazywany jest parametr entries
, który jest tablicą obiektów IntersectionObserverEntry
. Każdy taki obiekt zawiera zaktualizowane dane przecięcia jednego z obserwowanych przez Ciebie 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
jest wynikiem wywołania funkcji getBoundingClientRect()
w elemencie głównym, który domyślnie jest widoczny w widocznym obszarze. boundingClientRect
jest wynikiem wywołania getBoundingClientRect()
dla zaobserwowanego elementu. intersectionRect
to przecięcie tych 2 prostokątów i skutecznie informuje, którą część obserwowanego elementu jest widoczna. intersectionRatio
jest blisko powiązane i informuje, jaką część elementu jest widoczny. Dysponując tymi informacjami, możesz teraz wdrażać takie funkcje jak ładowanie zasobów dokładnie w czasie, zanim staną się one widoczne na ekranie. Efektywnie.
![Współczynnik przecięcia.](https://web.developers.google.cn/static/articles/intersectionobserver/image/intersection-ratio-cc2e11cc70559.png?authuser=6&hl=pl)
Reguły IntersectionObserver
dostarczają dane asynchronicznie, a kod wywołania zwrotnego jest uruchamiany w wątku głównym. Dodatkowo w specyfikacji znajduje się informacja, że implementacje IntersectionObserver
powinny używać requestIdleCallback()
. Oznacza to, że wywołanie zwrotne ma niski priorytet i jest wykonywane przez przeglądarkę w czasie bezczynności. To przemyślana decyzja dotycząca projektu.
Przewijane elementy div
Nie przepadam za przewijaniem wewnątrz elementu, ale nie mogę tu osądzać ani IntersectionObserver
. Obiekt options
ma opcję root
, która pozwala określić alternatywę dla widocznego obszaru jako element główny. Pamiętaj, że element root
musi być elementem nadrzędnym wszystkich obserwowanych elementów.
Łącz wszystkie te elementy.
Nie! Źle deweloper! Nie zwracamy uwagi na wykorzystanie cykli procesora przez użytkownika. Weźmy na przykład mechanizm przewijania nieskończonego: w takiej sytuacji warto dodać do elementu DOM waranty i obserwować je (i je poddawać recyklingowi). Dodaj strażnika blisko ostatniego elementu w przewijaniu nieskończonym. Kiedy pojawi się ten sygnał, możesz użyć wywołania zwrotnego do wczytania danych, utworzenia kolejnych elementów, dołączenia ich do modelu DOM i odpowiedniego zmiany położenia strażnika. Jeśli w praktyce zostanie oddane do recyklingu, nie trzeba będzie dodatkowo wywoływać funkcji observe()
. IntersectionObserver
nadal działa.
![Przewijanie nieskończone](https://web.developers.google.cn/static/articles/intersectionobserver/image/infinite-scroller-f23f2b90aa6bd.png?authuser=6&hl=pl)
Poproszę o więcej aktualizacji
Jak wspomnieliśmy wcześniej, wywołanie zwrotne zostanie aktywowane raz, gdy obserwowany element stanie się częściowo widoczny, i innym razem, gdy zniknie z widocznego obszaru. Dzięki temu IntersectionObserver
uzyska odpowiedź na pytanie „Czy element X jest widoczny?”. W niektórych przypadkach może to jednak nie wystarczyć.
W takim przypadku do akcji wkracza opcja threshold
. Umożliwia określenie tablicy intersectionRatio
progów. Wywołanie zwrotne będzie wywoływane za każdym razem, gdy intersectionRatio
przekroczy jedną z tych wartości. Domyślną wartością parametru threshold
jest [0]
. Opisuje ona działanie domyślne. Jeśli zmienimy threshold
na [0, 0.25, 0.5, 0.75, 1]
, będziemy powiadamiać Cię za każdym razem, gdy widoczny będzie dodatkowy kwartał elementu:
![Animacja progu.](https://web.developers.google.cn/static/articles/intersectionobserver/image/threshold-animation-818bf785c4e2d.gif?authuser=6&hl=pl)
Jakieś inne opcje?
Obecnie oprócz tych wymienionych powyżej dostępna jest tylko 1 opcja dodatkowa. rootMargin
umożliwia określenie marginesów rdzenia, co w praktyce pozwala powiększać lub zmniejszać obszar używany na potrzeby skrzyżowań. Marginesy określa się za pomocą ciągu w stylu CSS (á la "10px 20px 30px 40px"
), który określa odpowiednio górny, prawy, dolny i lewy margines. Podsumowując, struktura opcji IntersectionObserver
udostępnia 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>
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 tym, czy są na ekranie. Jeśli <iframe>
wykryje jeden z jego elementów, zarówno przewijanie elementu <iframe>
, jak i przewinięcie okna zawierającego ten znak <iframe>
spowoduje wywołanie zwrotne w odpowiednim momencie. W tym drugim przypadku wartość rootBounds
będzie jednak ustawiona na null
, aby uniknąć wycieku danych między źródłami.
Czym IntersectionObserver
nie jest?
Pamiętaj, że interfejs IntersectionObserver
celowo nie jest idealnym pikselem ani nie ma małego opóźnienia. Korzystanie z nich w celach takich jak animacje zależne od przewijania najprawdopodobniej zakończy się niepowodzeniem, ponieważ w chwili, gdy będziesz ich używać, dane staną się nieaktualne. Wyjaśnienie zawiera więcej informacji na temat pierwotnych przypadków użycia IntersectionObserver
.
Ile pracy mogę wykonać w ramach wywołania zwrotnego?
Short 'n Sweet: Poświęcanie zbyt długiego czasu na wywołanie zwrotne spowoduje opóźnienie aplikacji – mają zastosowanie wszystkie typowe praktyki.
Idź dalej i krzyżuj swoje elementy
Obsługa IntersectionObserver
w przeglądarkach działa dobrze, ponieważ jest dostępna we wszystkich nowoczesnych przeglądarkach. W razie potrzeby element polyfill jest dostępny w repozytorium WICG w starszych przeglądarkach. Oczywiście korzystanie z kodu Polyfill nie zwiększy wydajności, jaką daje implementacja natywna.
Możesz zacząć korzystać z IntersectionObserver
już teraz. Powiedz nam, co Ci wymyśliłeś.