Mit IntersectionObservers können Sie feststellen, wann ein beobachtetes Element den Darstellungsbereich des Browsers betritt oder verlässt.
Angenommen, Sie möchten erfassen, wann ein Element in Ihrem DOM in den sichtbaren Darstellungsbereich eintritt. So können Sie z. B. Lazy Loading für Bilder verwenden oder wissen, ob sich der Nutzer tatsächlich ein bestimmtes Anzeigenbanner ansieht. Dazu können Sie das Scroll-Ereignis verknüpfen oder einen regelmäßigen Timer verwenden und getBoundingClientRect()
auf dieses Element anwenden.
Dieser Ansatz ist jedoch sehr langsam, da bei jedem Aufruf von getBoundingClientRect()
der Browser das gesamte Layout der Seite neu erstellen muss. Das führt zu erheblichen Rucklern auf Ihrer Website. Es wird fast unmöglich, wenn Sie wissen, dass Ihre Website in einem Iframe geladen wird, und wissen möchten, wann der Nutzer ein Element sehen kann. Das Single-Origin-Modell und der Browser lassen keinen Zugriff auf Daten der Webseite zu, die den iFrame enthält. Dies ist ein häufiges Problem bei Anzeigen, die häufig mit iFrames geladen werden.
IntersectionObserver
wurde entwickelt, um diesen Sichtbarkeitstest effizienter zu gestalten, und ist in allen modernen Browsern verfügbar. IntersectionObserver
gibt Aufschluss darüber, wann ein beobachtetes Element in den Browser-Viewport eintritt oder ihn verlässt.
IntersectionObserver
erstellen
Die API ist eher klein und am besten anhand eines Beispiels beschrieben:
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();
Wenn Sie die Standardoptionen für IntersectionObserver
verwenden, wird Ihr Rückruf sowohl aufgerufen, wenn das Element teilweise sichtbar wird, als auch wenn es den Darstellungsbereich vollständig verlässt.
Wenn Sie mehrere Elemente beobachten müssen, ist es möglich und empfehlenswert, mehrere Elemente mit der gleichen IntersectionObserver
-Instanz zu beobachten, indem Sie observe()
mehrmals aufrufen.
An den Callback wird ein entries
-Parameter übergeben, der ein Array von IntersectionObserverEntry
-Objekten ist. Jedes solche Objekt enthält aktualisierte Kreuzungsdaten für eines Ihrer beobachteten Elemente.
🔽[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
ist das Ergebnis des Aufrufs von getBoundingClientRect()
auf das Stammelement, das standardmäßig der Darstellungsbereich ist. boundingClientRect
ist das Ergebnis von getBoundingClientRect()
, das auf das beobachtete Element angewendet wird. intersectionRect
ist die Schnittmenge dieser beiden Rechtecke und gibt an, welcher Teil des beobachteten Elements sichtbar ist. intersectionRatio
ist eng damit verwandt und gibt an, wie viel des Elements sichtbar ist. Mit diesen Informationen können Sie jetzt Funktionen wie das Just-in-Time-Laden von Assets implementieren, bevor sie auf dem Bildschirm sichtbar werden. effizient:
IntersectionObserver
s liefern ihre Daten asynchron und Ihr Callback-Code wird im Hauptthread ausgeführt. Außerdem heißt es in der Spezifikation, dass IntersectionObserver
-Implementierungen requestIdleCallback()
verwenden sollten. Das bedeutet, dass der Aufruf an den bereitgestellten Callback eine niedrige Priorität hat und vom Browser während der Inaktivität ausgeführt wird. Dies ist eine bewusste Designentscheidung.
Scrollende Divs
Ich bin kein großer Fan von Scrollen innerhalb eines Elements, aber ich bin nicht hier, um zu urteilen, und das ist auch IntersectionObserver
nicht. Für das Objekt options
wird eine root
-Option verwendet, mit der Sie eine Alternative zum Darstellungsbereich als Stamm definieren können. root
muss ein Ancestor aller beobachteten Elemente sein.
Kombiniere alles!
Nein! Schlechter Entwickler! Das ist keine sinnvolle Nutzung der CPU-Zyklen Ihrer Nutzer. Sehen wir uns als Beispiel einen unendlichen Scroller an: In diesem Szenario ist es definitiv ratsam, dem DOM Sentinels hinzuzufügen und diese zu beobachten und wiederzuverwenden. Sie sollten einen Sentinel nahe dem letzten Element im unendlichen Scroller hinzufügen. Wenn dieser Sentinel in Sicht kommt, kannst du mit dem Rückruf Daten laden, die nächsten Elemente erstellen, sie an das DOM anhängen und den Sentinel entsprechend neu positionieren. Wenn Sie den Sentinel ordnungsgemäß wiederverwenden, ist kein zusätzlicher Aufruf von observe()
erforderlich. Die IntersectionObserver
funktioniert weiter.
Mehr Updates
Wie bereits erwähnt, wird der Rückruf einmal ausgelöst, wenn das beobachtete Element teilweise sichtbar wird, und noch einmal, wenn es den Darstellungsbereich verlässt. So erhalten Sie mit IntersectionObserver
eine Antwort auf die Frage: „Ist Element X im Blickfeld?“ In einigen Anwendungsfällen reicht das jedoch nicht aus.
Hier kommt die Option threshold
ins Spiel. Sie können damit eine Reihe von intersectionRatio
-Grenzwerten definieren. Dein Callback wird jedes Mal aufgerufen, wenn intersectionRatio
einen dieser Werte überschreitet. Der Standardwert für threshold
ist [0]
. Dies erklärt das Standardverhalten. Wenn wir threshold
in [0, 0.25, 0.5, 0.75, 1]
ändern, werden wir jedes Mal benachrichtigt, wenn ein weiteres Viertel des Elements sichtbar wird:
Haben Sie noch andere Möglichkeiten?
Derzeit gibt es nur eine zusätzliche Option zu den oben aufgeführten. Mit rootMargin
können Sie die Ränder für den Stamm angeben und so den Bereich für Überschneidungen vergrößern oder verkleinern. Diese Ränder werden mithilfe eines CSS-Strings wie "10px 20px 30px 40px"
angegeben, der jeweils den oberen, rechten, unteren und linken Rand angibt. Zusammenfassend bietet das Options-Objekt IntersectionObserver
folgende Optionen:
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>
-Magie
IntersectionObserver
wurden speziell für Werbedienste und Widgets für soziale Netzwerke entwickelt, die häufig <iframe>
-Elemente verwenden und von Vorteil sein könnten, wenn sie wissen, ob sie sichtbar sind. Wenn ein <iframe>
eines seiner Elemente beobachtet, wird der Callback sowohl beim Scrollen des <iframe>
als auch beim Scrollen des Fensters , das das <iframe>
enthält, zum richtigen Zeitpunkt ausgelöst. Im letzteren Fall wird rootBounds
jedoch auf null
gesetzt, um Datenlecks über mehrere Quellen hinweg zu vermeiden.
Wozu dient IntersectionObserver
Nicht?
Beachte bitte, dass IntersectionObserver
bewusst weder pixelgenau noch mit geringer Latenz ist. Die Verwendung dieser Daten für die Implementierung von Elementen wie scrollabhängigen Animationen ist zum Scheitern verurteilt, da die Daten zum Zeitpunkt der Verwendung streng genommen veraltet sind. In der Erläuterung finden Sie weitere Informationen zu den ursprünglichen Anwendungsfällen für IntersectionObserver
.
Wie viel Arbeit kann ich im Rückruf erledigen?
Kurz und bündig: Wenn der Rückruf zu lange dauert, kommt es zu Verzögerungen bei der App. Hier gelten alle gängigen Praktiken.
Gehe hin und schneide die Elemente
IntersectionObserver
wird von allen modernen Browsern unterstützt. Bei Bedarf kann in älteren Browsern eine Polyfill verwendet werden, die im Repository des W3C verfügbar ist. Natürlich können Sie mit dieser Polyfill nicht die Leistungsvorteile erzielen, die eine native Implementierung bietet.
Sie können IntersectionObserver
sofort verwenden. Erzählen Sie uns, was Sie herausgefunden haben.