IntersectionObserver kommt in Sicht

IntersectionObservers informieren Sie, wenn ein beobachtetes Element den Darstellungsbereich des Browsers betritt oder verlässt.

Unterstützte Browser

  • 51
  • 15
  • 55
  • 12.1

Quelle

Angenommen, Sie möchten erfassen, wann ein Element in Ihrem DOM in den sichtbaren Darstellungsbereich eintritt. So können Sie zum Beispiel Lazy Loading für Bilder verwenden oder wissen, ob sich der Nutzer tatsächlich ein bestimmtes Werbebanner ansieht. Aktivieren Sie dazu das Scroll-Ereignis oder verwenden Sie einen regelmäßigen Timer und rufen Sie getBoundingClientRect() auf. für dieses Element.

Dieser Ansatz ist jedoch mühsam langsam, da jeder Aufruf von getBoundingClientRect() den Browser dazu zwingt, das Layout der gesamten Seite neu zu erstellen, was zu erheblichen Verzögerungen auf Ihrer Website führt. Wenn Sie wissen, dass Ihre Website innerhalb eines iFrames geladen wird, und Sie wissen möchten, wann der Nutzer ein Element sehen kann, wird die Situation nahezu unmöglich. 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.

Diesen Sichtbarkeitstest effizienter zu gestalten, wurde IntersectionObserver für entwickelt und wird in allen modernen Browsern verwendet. IntersectionObserver informiert Sie, wenn ein beobachtetes Element den Darstellungsbereich des Browsers betritt oder verlässt.

iFrame-Sichtbarkeit

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 Callback sowohl dann aufgerufen, wenn das Element teilweise sichtbar ist, 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 derselben IntersectionObserver-Instanz zu beobachten, indem Sie observe() mehrmals aufrufen.

Ein entries-Parameter wird an den Callback übergeben. Dieser ist ein Array von IntersectionObserverEntry-Objekten. Jedes dieser Objekte enthält aktualisierte Schnittdaten für eines der 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() für das Stammelement. Dies ist standardmäßig der Darstellungsbereich. boundingClientRect ist das Ergebnis von getBoundingClientRect(), das für das beobachtete Element aufgerufen wird. intersectionRect ist die Schnittmenge dieser beiden Rechtecke und gibt an, welcher Teil des beobachteten Elements sichtbar ist. intersectionRatio ist eng miteinander verbunden 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.

Kreuzungsverhältnis

IntersectionObservers stellen ihre Daten asynchron bereit und dein Callback-Code wird im Hauptthread ausgeführt. Die Spezifikation besagt außerdem, dass bei IntersectionObserver-Implementierungen requestIdleCallback() verwendet werden sollte. 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 div-Elemente

Ich bin kein großer Fan von Scrollen in einem Element, aber das kann ich nicht beurteilen – und das ist auch nicht IntersectionObserver. 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 macht die Nutzung der CPU-Zyklen des Nutzers nicht achtsam. 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 sichtbar wird, können Sie den Callback verwenden, um Daten zu laden, die nächsten Elemente zu erstellen, sie an das DOM anzuhängen und den Sentinel entsprechend neu zu positionieren. Wenn Sie die Sentinel ordnungsgemäß recyceln, ist kein zusätzlicher Aufruf von observe() erforderlich. IntersectionObserver funktioniert weiterhin.

Unendliches Scrollen

Weitere Updates

Wie bereits erwähnt, wird der Callback einmal ausgelöst, wenn das beobachtete Element teilweise sichtbar ist, und ein weiteres Mal, wenn es den Darstellungsbereich verlassen hat. So erhalten Sie mit IntersectionObserver eine Antwort auf die Frage „Ist Element X in Sicht?“. In einigen Anwendungsfällen reicht das jedoch nicht aus.

Hier kommt die Option threshold ins Spiel. Sie können ein Array von intersectionRatio-Schwellenwerten 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 zu [0, 0.25, 0.5, 0.75, 1] ändern, werden wir jedes Mal benachrichtigt, wenn ein weiteres Viertel des Elements sichtbar wird:

Grenzwertanimation.

Haben Sie noch andere Möglichkeiten?

Derzeit gibt es nur eine zusätzliche Option als die oben aufgeführten. Mit rootMargin können Sie die Ränder für die Wurzel festlegen und so die Fläche für Kreuzungen 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 lässt sich sagen, dass die IntersectionObserver-Optionsstruktur die folgenden Optionen bietet:

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 erkennt, wird der Callback zu den entsprechenden Zeitpunkten ausgelöst – sowohl beim Scrollen des <iframe>-Elements als auch beim Scrollen des Fensters, das <iframe> enthält. Im letzteren Fall wird rootBounds jedoch auf null gesetzt, um Datenlecks über mehrere Quellen hinweg zu vermeiden.

Worum geht es bei IntersectionObserver nicht?

Zu beachten ist, dass IntersectionObserver absichtlich weder Pixel perfekt ist noch eine niedrige Latenz hat. Ihre Verwendung zur Implementierung von Aktionen wie scrollbaren Animationen wird wahrscheinlich fehlschlagen, da die Daten – streng genommen – veraltet sind, wenn Sie sie verwenden werden. In der Erläuterung finden Sie weitere Informationen zu den ursprünglichen Anwendungsfällen für IntersectionObserver.

Wie viel Arbeit kann ich mit dem Rückruf machen?

Kurz und knackig: Wenn Sie zu viel Zeit mit dem Callback verbringen, kommt es zu Verzögerungen in Ihrer App. Dabei gelten alle gängigen Praktiken.

Geh weiter und überlege dir die Elemente

Die Browserunterstützung für IntersectionObserver ist gut, da sie in allen modernen Browsern verfügbar ist. Bei Bedarf kann in älteren Browsern ein Polyfill verwendet werden. Dieses ist im WICG-Repository verfügbar. Offensichtlich profitieren Sie mit diesem Polyfill nicht von den Leistungsvorteilen, die Sie mit einer nativen Implementierung erzielen würden.

Sie können IntersectionObserver jetzt verwenden. Sag uns, was du dir ausgedacht hast.