IntersectionObserver kommt in Sicht

IntersectionObservers informieren Sie, wenn ein beobachtetes Element in den Darstellungsbereich des Browsers eintritt oder diesen 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 Bilder rechtzeitig zum Lazy Loading laden oder wissen, ob sich der Nutzer tatsächlich ein bestimmtes Anzeigenbanner ansieht. Dazu können Sie das Scroll-Ereignis einbinden oder einen regelmäßigen Timer verwenden und getBoundingClientRect() für dieses Element aufrufen.

Dieser Ansatz ist allerdings ziemlich langsam, da jeder Aufruf von getBoundingClientRect() den Browser dazu zwingt, das Layout der gesamten Seite neu zu gestalten, 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, ist dies fast unmöglich. Mit dem Single-Origin-Modell und dem Browser können Sie nicht auf Daten der Webseite zugreifen, die den iFrame enthält. Dies tritt häufig bei Anzeigen auf, die häufig mit iFrames geladen werden.

IntersectionObserver wurde für einen effizienteren Sichtbarkeitstest entwickelt und ist jetzt in allen modernen Browsern verfügbar. IntersectionObserver gibt an, wann ein beobachtetes Element in den Darstellungsbereich des Browsers eintritt oder diesen verlässt.

iFrame-Sichtbarkeit

IntersectionObserver erstellen

Die API ist eher 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 der Callback sowohl dann aufgerufen, wenn das Element teilweise zu sehen ist, als auch, wenn es den Darstellungsbereich vollständig verlässt.

Wenn Sie mehrere Elemente beobachten müssen, ist es sowohl möglich als auch empfehlenswert, mehrere Elemente mit derselben IntersectionObserver-Instanz zu beobachten, indem Sie observe() mehrmals aufrufen.

Ein entries-Parameter wird an Ihren Callback übergeben, bei dem es sich um ein Array von IntersectionObserverEntry-Objekten handelt. Jedes dieser Objekte enthält aktualisierte Kreuzungsdaten 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, das standardmäßig der Darstellungsbereich ist. boundingClientRect ist das Ergebnis von getBoundingClientRect(), das für das beobachtete Element aufgerufen wurde. intersectionRect ist die Schnittmenge dieser beiden Rechtecke. Sie zeigt effektiv an, welcher Teil des beobachteten Elements sichtbar ist. intersectionRatio steht in engem Zusammenhang und gibt an, wie viel vom Element sichtbar ist. Dank dieser Informationen können Sie jetzt Funktionen wie das Just-in-Time-Laden von Assets implementieren, bevor sie auf dem Bildschirm sichtbar werden. effizient.

Schnittverhältnisse

IntersectionObservers liefern ihre Daten asynchron und der Callback-Code wird im Hauptthread ausgeführt. Außerdem steht in der Spezifikation, dass IntersectionObserver-Implementierungen requestIdleCallback() verwenden sollen. Das bedeutet, dass der Aufruf Ihres bereitgestellten Callbacks eine niedrige Priorität hat und vom Browser bei Inaktivität ausgeführt wird. Dies ist eine bewusste Designentscheidung.

Scrollende Divs

Ich mag es nicht, innerhalb eines Elements zu scrollen, aber ich bin nicht hier, um ein Urteil zu fällen, und IntersectionObserver auch nicht. Für das Objekt options wird die Option root verwendet, mit der Sie eine Alternative zum Darstellungsbereich als Stamm definieren können. Beachten Sie, dass root ein Ancestor aller beobachteten Elemente sein muss.

Alle Elemente überschneiden sich!

Nein! Schlechter Entwickler! Dabei geht es nicht um die bewusste Nutzung der CPU-Zyklen. Betrachten wir als Beispiel einen unendlichen Scroller: In diesem Szenario ist es definitiv ratsam, Sentinels zum DOM hinzuzufügen und diese zu beobachten (und wiederverwenden). Fügen Sie einen Sentinel nahe an das letzte Element im unendlichen Scrollen hinzu. Wenn dieser Sentinel zu sehen ist, 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 den Sentinel ordnungsgemäß recyceln, ist kein zusätzlicher Aufruf an observe() erforderlich. IntersectionObserver funktioniert weiterhin.

Unendliches Scrollen

Weitere Updates bitte

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

Hier kommt die Option threshold ins Spiel. Damit können Sie ein Array von intersectionRatio-Schwellenwerten definieren. Der Callback wird immer dann 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:

Grenzwertanimation.

Haben Sie noch weitere Möglichkeiten?

Derzeit gibt es nur eine zusätzliche Option. Mit rootMargin können Sie die Ränder für die Stammfläche angeben. So lässt sich der Bereich für Kreuzungen vergrößern oder verkleinern. Diese Ränder werden mithilfe eines CSS-Strings, á la "10px 20px 30px 40px", angegeben, wobei der obere, rechte, untere und linke Rand angegeben werden. Zusammenfassend lässt sich sagen, dass die Struktur der IntersectionObserver-Optionen 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],
});

Magie von <iframe>

IntersectionObservers wurden speziell für Werbedienste und Widgets für soziale Netzwerke entwickelt, die häufig <iframe>-Elemente verwenden und daher davon profitieren könnten, zu wissen, ob sie sichtbar sind. Wenn ein <iframe> eines seiner Elemente erkennt, wird sowohl durch das Scrollen der <iframe> als auch das Scrollen des Fensters, mit dem <iframe> gescrollt, der Callback zu den entsprechenden Zeiten ausgelöst. Im letzteren Fall wird rootBounds jedoch auf null gesetzt, um zu verhindern, dass Daten ursprungsübergreifend übertragen werden.

Worum geht es bei IntersectionObserver nicht?

Beachten Sie außerdem, dass IntersectionObserver absichtlich weder pixelgenau perfekt ist noch eine niedrige Latenz aufweist. Wenn Sie sie für die Implementierung von Aufgaben wie scrollabhängigen Animationen verwenden, werden die Daten zu dem Zeitpunkt, zu dem Sie sie nutzen können, veraltet sein. In der Erklärung findest du weitere Details zu den ursprünglichen Anwendungsfällen für IntersectionObserver.

Was kann ich im Callback tun?

Short 'n Sweet: Wenn Sie zu viel Zeit in den Callback investieren, verzögert sich Ihre App – es gelten alle gängigen Methoden.

Gehe vor und kreuze deine Elemente

Die Browserunterstützung für IntersectionObserver ist gut, da sie in allen modernen Browsern verfügbar ist. Bei Bedarf kann ein Polyfill in älteren Browsern verwendet werden und ist im WICG-Repository verfügbar. Offensichtlich erhalten Sie mit diesem Polyfill keine Leistungsvorteile, die Ihnen eine native Implementierung bieten würde.

Du kannst IntersectionObserver sofort nutzen. Was haben Sie sich ausgedacht?