IntersectionObserver kommt in Sicht

Mit IntersectionObservers können Sie feststellen, wann ein beobachtetes Element den Darstellungsbereich des Browsers betritt oder verlässt.

Unterstützte Browser

  • Chrome: 51.
  • Edge: 15.
  • Firefox: 55.
  • Safari: 12.1.

Quelle

Angenommen, Sie möchten erfassen, wann ein Element in Ihrem DOM in den sichtbaren Darstellungsbereich gelangt. Das kann beispielsweise sinnvoll sein, wenn Sie Bilder genau dann laden möchten, wenn sie benötigt werden, oder wenn Sie wissen möchten, ob sich der Nutzer ein bestimmtes Anzeigenbanner ansieht. Dazu können Sie das Scroll-Ereignis verknüpfen oder einen periodischen Timer verwenden und getBoundingClientRect() auf dieses Element anwenden.

Dieser Ansatz ist jedoch sehr langsam, da jeder Aufruf von getBoundingClientRect() den Browser dazu zwingt, das gesamte Layout der Seite neu zu erstellen. Außerdem führt er 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. Aufgrund des Modells mit einer einzigen Quelle und des Browsers können Sie nicht auf Daten von der Webseite zugreifen, die den iframe enthält. Das ist beispielsweise ein häufiges Problem bei Anzeigen, die häufig über Iframes geladen werden.

IntersectionObserver wurde entwickelt, um diesen Sichtbarkeitstest effizienter zu gestalten. Er 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.

Sichtbarkeit von iFrames

IntersectionObserver erstellen

Die API ist recht klein und lässt sich am besten anhand eines Beispiels beschreiben:

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 Ihren Callback wird ein entries-Parameter übergeben, der ein Array von IntersectionObserverEntry-Objekten ist. Jedes solche Objekt enthält aktualisierte Daten zu Überschneidungen 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:

Schnittverhältnis.

IntersectionObservers 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 Ihres bereitgestellten Rückrufs eine niedrige Priorität hat und vom Browser während der Inaktivität ausgeführt wird. Das 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. Das Objekt options hat die Option root, mit der Sie eine Alternative zum Viewport als Wurzel definieren können. Beachten Sie, dass root ein Vorfahr aller beobachteten Elemente sein muss.

Alle Daten zusammenführen

Nein! Schlechter Entwickler! Das ist keine sinnvolle Nutzung der CPU-Zyklen Ihrer Nutzer. Denken wir zum Beispiel an einen endlosen Scroller: 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 endlosen 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.

Unendlicher Scroller

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 möglicherweise nicht aus.

Hier kommt die Option threshold ins Spiel. Sie können damit eine Reihe von intersectionRatio-Grenzwerten definieren. Ihr Callback wird jedes Mal aufgerufen, wenn intersectionRatio einen dieser Werte überschreitet. Der Standardwert für threshold ist [0], was das Standardverhalten erklärt. 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:

Schwellenwertanimation.

Gibt es noch andere Optionen?

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 mit einem CSS-String wie "10px 20px 30px 40px" angegeben, wobei jeweils der obere, rechte, untere und linke Rand angegeben wird. 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> magischer Befehl

IntersectionObservers wurden speziell für Werbedienste und Widgets in sozialen Netzwerken entwickelt, in denen häufig <iframe>-Elemente verwendet werden und die davon profitieren könnten, zu wissen, ob sie im Sichtfeld 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 zwischen Ursprüngen 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 Callback zu lange dauert, kommt es zu Verzögerungen bei der App. Hier gelten alle gängigen Praktiken.

Gehen Sie vor und überschneiden Sie 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.