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.
  • Rand: 15.
  • Firefox: 55.
  • Safari: 12.1.

Quelle

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.

Sichtbarkeit von iFrames

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:

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 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.

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 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:

Schwellenwertanimation.

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.