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ż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.
Takie podejście jest jednak bardzo powolne, ponieważ każde wywołanie funkcji getBoundingClientRect()
powoduje, że przeglądarka musi ponownie ułożyć całą stronę, co spowoduje znaczne spowolnienie działania 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.
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();
Przy użyciu domyślnych opcji funkcji IntersectionObserver
wywołanie zwrotne zostanie wywołane zarówno wtedy, gdy element jest częściowo widoczny, jak i gdy całkowicie zniknie z widocznego obszaru.
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.
IntersectionObserver
przesyła dane asynchronicznie, a kod wywołania zwrotnego będzie wykonywany w wątku głównym. Dodatkowo w specyfikacji znajduje się informacja, ż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. To przemyślana decyzja dotycząca projektu.
Elementy div z przewijaniem
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.
Przecięcie wszystkich rzeczy!
Nie! Niewłaściwy deweloper To nie jest rozsądne wykorzystanie cykli procesora 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). Należy dodać element kontrolny w pobliżu ostatniego elementu w nieskończonym scrollerze. 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.
Więcej informacji
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. W ten sposób IntersectionObserver
odpowiada 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 definiowanie tablic progów intersectionRatio
. 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:
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ń. 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],
});
<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 projekt IntersectionObserver
celowo nie jest idealnym pikselem ani nie ma małego opóźnienia. Ich wykorzystanie do implementacji takich rozwiązań jak animacje zależne od przewijania jest skazane na niepowodzenie, ponieważ do czasu, gdy zechcesz z nich skorzystać, dane będą nieaktualne. Więcej informacji o pierwotnych przypadkach użycia funkcji IntersectionObserver
znajdziesz w tym artykule.
Jak wiele mogę zrobić podczas rozmowy zwrotnej?
Short 'n Sweet: Poświęcanie zbyt długiego czasu na wywołanie zwrotne spowoduje opóźnienie aplikacji – mają zastosowanie wszystkie typowe praktyki.
Idźcie i przenikajcie elementy
Obsługa IntersectionObserver
w przeglądarkach działa dobrze, ponieważ jest dostępna we wszystkich nowoczesnych przeglądarkach. W starszych przeglądarkach można użyć polyfilla, który jest dostępny w repozytorium WICG. 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 udało Ci się znaleźć.