Intersection Observer API
Baseline
Widely available
*
This feature is well established and works across many devices and browser versions. It’s been available across browsers since März 2019.
* Some parts of this feature may have varying levels of support.
Die Intersection Observer API bietet eine Möglichkeit, asynchron Änderungen in der Schnittmenge eines Zielelements mit einem Vorfahrenelement oder mit dem Viewport eines obersten Dokuments zu beobachten.
Überblick
Historisch gesehen war das Erkennen der Sichtbarkeit eines Elements oder der relativen Sichtbarkeit zweier Elemente zueinander eine schwierige Aufgabe, für die die Lösungen oft unzuverlässig waren und dazu neigten, den Browser und die Websites, die der Benutzer aufruft, zu verlangsamen. Während das Web gereift ist, ist der Bedarf an dieser Art von Informationen gewachsen. Schnittstelleninformationen werden aus vielen Gründen benötigt, wie zum Beispiel:
- Lazy-Loading von Bildern oder anderem Inhalt, während eine Seite gescrollt wird.
- Implementierung von "unendlichen Scroll"-Webseiten, bei denen mehr und mehr Inhalt geladen und gerendert wird, während Sie scrollen, sodass der Benutzer nicht durch Seiten blättern muss.
- Berichterstattung über die Sichtbarkeit von Anzeigen, um Werbeeinnahmen zu berechnen.
- Entscheidung, ob Aufgaben oder Animationsprozesse basierend darauf durchgeführt werden sollen, ob der Benutzer das Ergebnis sehen wird oder nicht.
Die Implementierung der Schnittstellenerkennung in der Vergangenheit beinhaltete Ereignis-Handler und Schleifen, die Methoden wie Element.getBoundingClientRect() aufriefen, um die benötigten Informationen für jedes betroffene Element zu erstellen. Da all dieser Code im Hauptthread ausgeführt wird, kann selbst einer von ihnen Leistungsprobleme verursachen. Wenn eine Website mit diesen Tests geladen wird, kann es regelrecht unangenehm werden.
Betrachten Sie eine Webseite, die unendliches Scrollen verwendet. Sie verwendet eine vom Anbieter bereitgestellte Bibliothek, um die Anzeigen zu verwalten, die periodisch auf der Seite platziert werden, verfügt über animierte Grafiken hier und da, und verwendet eine benutzerdefinierte Bibliothek, die Benachrichtigungsfelder und dergleichen zeichnet. Jede dieser Funktionen hat ihre eigenen Routinen zur Schnittstellenerkennung, die alle im Hauptthread ausgeführt werden. Der Ersteller der Website bemerkt möglicherweise nicht einmal, dass dies geschieht, da er möglicherweise nur wenig über die inneren Abläufe der beiden verwendeten Bibliotheken weiß. Während der Benutzer die Seite scrollt, werden diese Routinen zur Schnittstellenerkennung ständig ausgeführt, was zu einer Erfahrung führt, die den Benutzer mit dem Browser, der Website und seinem Computer frustriert.
Die Intersection Observer API ermöglicht es dem Code, eine Callback-Funktion zu registrieren, die immer dann ausgeführt wird, wenn ein bestimmtes Element eine Schnittstelle mit einem anderen Element (oder dem Viewport) betritt oder verlässt oder wenn die Schnittstelle zwischen zwei Elementen um einen bestimmten Betrag geändert wird. Auf diese Weise müssen Websites im Hauptthread nichts tun, um diese Art von Schnittstellenelementen zu überwachen, und der Browser kann die Verwaltung der Schnittstellen nach eigenem Ermessen optimieren.
Eine Sache, die die Intersection Observer API nicht kann: Logik basierend auf der genauen Anzahl von überlappenden Pixeln auslösen oder speziell darauf, welche es sind. Sie löst nur den häufigen Anwendungsfall "Wenn sie sich irgendwo um N% überlappen, muss ich etwas tun" aus.
Konzepte und Verwendung
Die Intersection Observer API ermöglicht es Ihnen, einen Callback zu konfigurieren, der aufgerufen wird, wenn eine der folgenden Bedingungen eintritt:
- Ein Ziel-Element überschneidet entweder den Viewport des Geräts oder ein angegebenes Element. Dieses angegebene Element wird für die Zwecke der Intersection Observer API als Root-Element oder Root bezeichnet.
- Das erste Mal, wenn der Observer angewiesen wird, ein Zielelement zu beobachten.
In der Regel möchten Sie Änderungen an der Schnittstelle in Bezug auf den nächsten scrollbaren Vorfahren des Zielelements beobachten oder, wenn das Zielelement kein Nachkomme eines scrollbaren Elements ist, den Viewport des Geräts. Um die Schnittstelle relativ zum Viewport des Geräts zu beobachten, geben Sie null für die root-Option an. Lesen Sie weiter für eine detailliertere Erklärung zu den Optionen des Schnittstellenobservers.
Unabhängig davon, ob Sie den Viewport oder ein anderes Element als Root verwenden, funktioniert die API auf die gleiche Weise, indem sie eine Callback-Funktion ausführt, die Sie bereitstellen, wann immer sich die Sichtbarkeit des Zielelements ändert, so dass es gewünschte Mengen von Schnittstellen mit dem Root überschreitet.
Der Grad der Schnittstelle zwischen dem Zielelement und seinem Root ist das Schnittstellenverhältnis. Dies ist eine Darstellung des Prozentsatzes des Zielelements, das als Wert zwischen 0,0 und 1,0 sichtbar ist.
Erstellen eines Intersection Observers
Erstellen Sie den Intersection Observer, indem Sie seinen Konstruktor aufrufen und ihm eine Callback-Funktion übergeben, die ausgeführt wird, wann immer ein Schwellenwert in die eine oder andere Richtung überschritten wird:
const options = {
root: document.querySelector("#scrollArea"),
rootMargin: "0px",
scrollMargin: "0px",
threshold: 1.0,
};
const observer = new IntersectionObserver(callback, options);
Ein Schwellenwert von 1,0 bedeutet, dass die Callback-Funktion aufgerufen wird, wenn 100 % des Ziels innerhalb des durch die root-Option angegebenen Elements sichtbar sind.
Optionen des Intersection Observers
Das in den Konstruktor IntersectionObserver() übergebene options-Objekt ermöglicht es Ihnen, die Bedingungen zu steuern, unter denen der Callback des Obsservers aufgerufen wird. Es hat die folgenden Felder:
root-
Das Element, das als Viewport zur Überprüfung der Sichtbarkeit des Ziels verwendet wird. Muss der Vorfahre des Ziels sein. Standardmäßig wird der Browser-Viewport verwendet, wenn nicht angegeben oder
null. rootMargin-
Rand um den Root. Eine Zeichenkette von einem bis vier Werten ähnlich der CSS-Eigenschaft
margin, z.B."10px 20px 30px 40px"(oben, rechts, unten, links). Die Werte können nur in Pixel (px) oder Prozentsätzen (%) angegeben werden. Dieses Set von Werten dient dazu, jede Seite des umrahmten Rahmens des Root-Elements zu vergrößern oder zu verkleinern, bevor Schnittstellen berechnet werden. Negative Werte verkleinern den umrahmten Rahmen des Root-Elements und positive Werte vergrößern ihn. Der Standardwert, wenn nicht angegeben, ist"0px 0px 0px 0px". scrollMargin-
Rand um verschachtelte scroll-container, die dieselben Werte verwenden/die gleiche Standardeinstellung wie
rootMarginhaben. Die Ränder werden auf verschachtelte scrollbare Container angewendet, bevor Schnittstellen berechnet werden. Positive Werte vergrößern das Abschneidrechteck des Containers, sodass Ziele die Schnittstelle überschreiten können, bevor sie sichtbar werden, während negative Werte das Abschneidrechteck verkleinern. threshold-
Entweder eine einzelne Zahl oder ein Array von Zahlen, die angeben, bei welchem Prozentsatz der Sichtbarkeit des Ziels der Callback des Observers ausgeführt werden soll. Wenn Sie nur erfassen möchten, wenn die Sichtbarkeit die 50%-Marke überschreitet, können Sie einen Wert von 0,5 verwenden. Wenn der Callback jedes Mal ausgeführt werden soll, wenn die Sichtbarkeit um weitere 25% steigt, würden Sie das Array [0, 0.25, 0.5, 0.75, 1] angeben. Standardwert ist 0 (was bedeutet, dass der Callback ausgeführt wird, sobald das Zielelement die Grenze des Rootes überschneidet oder berührt, auch wenn noch keine Pixel sichtbar sind). Ein Wert von 1,0 bedeutet, dass der Schwellenwert nicht als erreicht betrachtet wird, bis jedes Pixel sichtbar ist.
delayExperimentell-
Wenn die Sichtbarkeit des Ziels (trackVisibility ist
true) verfolgt wird, kann dies verwendet werden, um die minimale Verzögerung in Millisekunden zwischen den Benachrichtigungen dieses Observers festzulegen. Ein Limit der Benachrichtigungsrate ist wünschenswert, da die Sichtbarkeitsberechnung rechenintensiv ist. Wenn die Sichtbarkeit verfolgt wird, wird der Wert auf 100 gesetzt, wenn er unter 100 liegt, und Sie sollten den größten tolerierbaren Wert verwenden. Der Standardwert ist 0. trackVisibilityExperimentell-
Ein Boolean, der angibt, ob dieser
IntersectionObserverÄnderungen in der Sichtbarkeit eines Ziels verfolgt.Wenn
false, meldet der Browser Schnittstellen, wenn das Zielelement in den Viewport des Root-Elements scrollt. Wenntrue, überprüft der Browser zusätzlich, ob das Ziel tatsächlich sichtbar ist und nicht von anderen Elementen überdeckt wird oder möglicherweise durch einen Filter zerstört oder versteckt, die Opazität reduziert oder durch irgendeine Transformation verborgen wurde. Der Standardwert istfalse, da die Verfolgung der Sichtbarkeit rechenintensiv ist. Wenn dies eingestellt ist, sollte auch einedelayfestgelegt werden.
Schnittstellenänderungs-Callbacks
Der an den Konstruktor IntersectionObserver() übergebene Callback erhält eine Liste von IntersectionObserverEntry Objekten und den Observer:
const callback = (entries, observer) => {
entries.forEach((entry) => {
// Each entry describes an intersection change for one observed
// target element:
// entry.boundingClientRect
// entry.intersectionRatio
// entry.intersectionRect
// entry.isIntersecting
// entry.rootBounds
// entry.target
// entry.time
});
};
Die Liste der vom Callback empfangenen Einträge enthält ein IntersectionObserverEntry-Objekt für jedes Ereignis beim Überschreiten eines Schwellenwerts – es können mehrere Einträge gleichzeitig empfangen werden, entweder von mehreren Zielen oder von einem einzelnen Ziel, das in kurzer Zeit mehrere Schwellenwerte überschreitet. Die Einträge werden mithilfe einer Schlange gesendet, sodass sie nach der Zeit geordnet sein sollten, zu der sie generiert wurden, aber Sie sollten vorzugsweise IntersectionObserverEntry.time verwenden, um sie korrekt zu ordnen. Jeder Eintrag beschreibt, wie viel eines bestimmten Elements mit dem Root-Element schneidet, ob das Element als schneidend betrachtet wird oder nicht, etc. Der Eintrag enthält nur Informationen über diesen speziellen Moment – wenn Sie Informationen benötigen, die eine Verfolgung über die Zeit erfordern, wie die Scroll-Richtung und -Geschwindigkeit, müssen Sie dies möglicherweise selbst berechnen, indem Sie zuvor empfangene Einträge merken.
Beachten Sie, dass Ihr Callback im Hauptthread ausgeführt wird. Er sollte so schnell wie möglich arbeiten; wenn etwas Zeitaufwändiges zu erledigen ist, verwenden Sie Window.requestIdleCallback().
Der unten stehende Code zeigt einen Callback, der mitzählt, wie oft Elemente vom nicht-schneidenden Zustand zum mindestens 75%-schneidenden Zustand übergehen. Bei einem Schwellenwert von 0,0 (Standard) wird der Callback ungefähr beim Übergang des booleschen Wertes von isIntersecting aufgerufen. Der Ausschnitt prüft daher zunächst, dass der Übergang ein positiver ist, und bestimmt dann, ob intersectionRatio über 75% liegt, in diesem Fall wird der Zähler erhöht.
const intersectionCallback = (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
let elem = entry.target;
if (entry.intersectionRatio >= 0.75) {
intersectionCounter++;
}
}
});
};
Ein Element zum Beobachten festlegen
Sobald Sie den Observer erstellt haben, müssen Sie ihm ein Zielelement zum Beobachten zuweisen:
const target = document.querySelector("#listItem");
observer.observe(target);
// the callback we set up for the observer will be executed now for the first time
// it waits until we assign a target to our observer (even if the target is currently not visible)
Wann immer das Ziel einen für den IntersectionObserver spezifizierten Schwellenwert erreicht, wird der Callback aufgerufen.
Beachten Sie auch, dass, wenn Sie die root-Option angegeben haben, das Ziel ein Nachkomme des Root-Elements sein muss.
Wie die Schnittstelle berechnet wird
Alle von der Intersection Observer API betrachteten Bereiche sind Rechtecke; Elemente, die unregelmäßig geformt sind, werden als in dem kleinsten Rechteck befindlich betrachtet, das alle Teile des Elements einschließt. Ebenso wird, wenn der sichtbare Teil eines Elements nicht rechteckig ist, das Schnittstellenrechteck des Elements als das kleinste Rechteck betrachtet, das alle sichtbaren Teile des Elements enthält.
Es ist nützlich, ein wenig darüber zu verstehen, wie die verschiedenen Eigenschaften, die von IntersectionObserverEntry bereitgestellt werden, eine Schnittstelle beschreiben.
Das Schnittstellen-Root und der Root-Rand
Bevor wir die Schnittstelle eines Elements mit einem Container verfolgen können, müssen wir wissen, was dieser Container ist. Dieser Container ist die Schnittstellen-Root oder das Root-Element. Dies kann entweder ein bestimmtes Element im Dokument sein, das ein Vorfahre des zu beobachtenden Elements ist, oder null, um den Viewport des Dokuments als Container zu verwenden.
Das Schnittstellen-Root-Rechteck ist das Rechteck, das verwendet wird, um gegen das Ziel oder die Ziele zu prüfen. Dieses Rechteck wird wie folgt bestimmt:
- Wenn die Schnittstellen-Root das implizierte Root (also das oberste
Document) ist, ist das Schnittstellen-Root-Rechteck das Rechteck des Viewports. - Wenn die Schnittstellen-Root einen Überlaufclip hat, ist das Schnittstellen-Root-Rechteck der Inhaltsbereich des Root-Elements.
- Andernfalls ist das Schnittstellen-Root-Rechteck das umrahmte Client-Rechteck der Schnittstellen-Root (wie es durch das Aufrufen von
getBoundingClientRect()darauf zurückgegeben wird).
Das Schnittstellen-Root-Rechteck kann weiter durch das Setzen des Root-Randes, rootMargin, beim Erstellen des IntersectionObserver angepasst werden. Die Werte in rootMargin definieren Offsets, die zu jeder Seite des umrahmten Rahmens des Root-Elements hinzugefügt werden, um die endgültigen Schnittstellen-Root-Grenzen zu erstellen (die in IntersectionObserverEntry.rootBounds offengelegt werden, wenn der Callback ausgeführt wird). Positive Werte vergrößern das Rechteck, während negative Werte es verkleinern. Jeder Offset-Wert kann nur in Pixel (px) oder als Prozentsatz (%) ausgedrückt werden.
Der Effekt, das Rechteck mit dem Root-Rand zu vergrößern, besteht darin, die Überlaufsziele die Schnittstelle mit dem Root überschreiten zu lassen, bevor sie sichtbar werden. Dies kann z. B. verwendet werden, um Bilder zu laden, kurz bevor sie in den Sichtbereich kommen, anstatt zu dem Zeitpunkt, an dem sie sichtbar werden.
Im Beispiel unten haben wir ein scrollbares Feld und ein Element, das anfangs nicht sichtbar ist. Sie können den rechten Rand des Root anpassen und sehen, dass:
- Wenn der Rand positiv ist, wird das rote Element als überschneidend mit dem Root betrachtet, auch wenn es nicht sichtbar ist, da es mit dem Randbereich des Root überschneidet.
- Wenn der Rand negativ ist, wird selbst dann, wenn das rote Element sichtbar wird, es nicht als überschneidend mit dem Root betrachtet, weil das umrahmte Rechteck des Root verkleinert wird.
Das Schnittstellen-Root und der Scroll-Rand
Betrachten Sie den Fall, bei dem Sie ein Root-Element haben, das verschachtelte scroll-container enthält, und Sie möchten Schnitte mit einem Ziel innerhalb eines dieser scrollbaren Container beobachten. Schnitte mit dem Zielelement beginnen standardmäßig beobachtbar zu werden, wenn das Ziel innerhalb des durch das Root definierten Bereichs sichtbar ist; anders gesagt, wenn der Container im Root sichtbar ist und das Ziel im Abschneidrechteck seines Containers sichtbar ist.
Sie können einen Scroll-Rand verwenden, um Schnitte zu beobachten, bevor oder nachdem das Ziel im Scroll-Container sichtbar wird. Der Rand wird auf alle verschachtelten scrollbaren Container im Root angewendet, einschließlich des Root-Elements, wenn es auch ein scrollbarer Container ist, und hat den Effekt, den für die Berechnung von Schnitten verwendeten Clipping-Bereich entweder zu vergrößern (positive Ränder) oder zu verkleinern (negativer Rand).
Hinweis:
Sie könnten eine Schnittstellen-Beobachter auf jedem Scroll-Container erstellen, für den Sie einen Scroll-Rand wünschen, und die rootMargin-Eigenschaft verwenden, um einen ähnlichen Effekt zu erzielen.
Die Verwendung eines Scroll-Randes ist ergonomischer, da Sie in den meisten Fällen nur einen Schnittstellen-Beobachter für alle verschachtelten Ziele haben können.
Im Beispiel unten haben wir ein scrollbares Feld und ein Bilderkarussell, das anfänglich nicht sichtbar ist. Ein Observer auf dem Root-Element beobachtet die Bildziele innerhalb des Karussells. Wenn ein Bildziel beginnt, sich mit dem Root-Element zu überschneiden, wird das Bild geladen, der Schnitt wird protokolliert und der Observer entfernt.
Scrollen Sie nach unten, um das Karussell anzuzeigen. Die sichtbaren Bilder sollten sofort geladen werden. Wenn Sie das Karussell scrollen, sollten Sie beobachten, dass die Bilder geladen werden, sobald das Element sichtbar wird.
Nachdem Sie das Beispiel zurückgesetzt haben, können Sie die bereitgestellte Steuerung verwenden, um den Scroll-Rand-Prozentsatz zu ändern. Wenn Sie einen positiven Wert von 20% setzen, wird das Clip-Rechteck des Scroll-Containers um 20% vergrößert, und Sie sollten beobachten, dass Bilder erkannt und geladen werden, bevor sie in den Sichtbereich kommen. In ähnlicher Weise bedeutet ein negativer Wert, dass der Schnitt erkannt wird, sobald die Bilder bereits sichtbar sind.
Schwellwerte
Anstatt jede infinitesimale Änderung in der Sichtbarkeit eines Zielelements zu melden, verwendet die Intersection Observer API Schwellwerte. Wenn Sie einen Beobachter erstellen, können Sie eine oder mehrere numerische Werte angeben, die die Prozentanteile des sichtbaren Zielelements repräsentieren. Dann meldet die API nur Änderungen in der Sichtbarkeit, die diese Schwellwerte überschreiten.
Zum Beispiel, wenn Sie jedes Mal informiert werden möchten, wenn die Sichtbarkeit eines Ziels rückwärts oder vorwärts durch jede 25% -Marke passiert, würden Sie das Array [0, 0.25, 0.5, 0.75, 1] als Liste der Schwellwerte beim Erstellen des Beobachters angeben.
Wenn der Callback aufgerufen wird, empfängt er eine Liste von IntersectionObserverEntry Objekten, eines für jedes beobachtete Ziel, das den Grad der Überschneidung mit dem Root geändert hat, so dass die exponierte Menge eine der Schwellenwerte in beiden Richtungen überschreitet.
Sie können sehen, ob das Ziel derzeit das Root überschneidet, indem Sie auf die isIntersecting-Eigenschaft des Eintrags schauen; wenn ihr Wert true ist, schneidet das Ziel das Root-Element oder Dokument zumindest teilweise. Auf diese Weise können Sie bestimmen, ob der Eintrag einen Übergang von den Elementen, die schneiden, zu denen, die nicht mehr schneiden, darstellt, oder einen Übergang von denen, die nicht schneiden, zu denen die schneiden.
Beachten Sie, dass es möglich ist, ein Schnittstellenrechteck von Null zu haben, was passieren kann, wenn der Schnittpunkt genau entlang der Grenze zwischen den beiden liegt oder das boundingClientRect von Null ist. Dieser Zustand, dass das Ziel und der Root eine Grenzlinie teilen, wird nicht als ausreichend betrachtet, um als Übergang in einen schneidenden Zustand zu gelten.
Um ein Gefühl dafür zu bekommen, wie Schwellwerte funktionieren, versuchen Sie, das Feld unten zu scrollen. Jede farbige Box darin zeigt den Prozentsatz ihrer selbst in allen vier Ecken an, sodass Sie sehen können, wie sich diese Verhältnisse im Laufe der Zeit ändern, während Sie den Container scrollen. Jede Box hat ein anderes Set von Schwellwerten:
- Die erste Box hat einen Schwellwert für jeden Prozentpunkt der Sichtbarkeit; das
IntersectionObserver.thresholds-Array ist[0.00, 0.01, 0.02, /*…,*/ 0.99, 1.00]. - Die zweite Box hat einen einzigen Schwellenwert bei der 50%-Marke.
- Die dritte Box hat Schwellenwerte alle 10% der Sichtbarkeit (0%, 10%, 20%, etc.).
- Die letzte Box hat Schwellenwerte alle 25%.
Verfolgen der Sichtbarkeit und Verzögerung
Standardmäßig gibt der Observer Benachrichtigungen aus, wenn das Zielelement in den Viewport des Root-Elements gescrollt wird. Während dies alles ist, was in vielen Situationen benötigt wird, ist es manchmal wichtig, dass Schnittstellen nicht gemeldet werden, wenn das Ziel "visuell beeinträchtigt" wurde. Zum Beispiel, bei der Messung von Analysen oder Werbeanzeigen-Eindrücken ist es wichtig, dass Zielelemente nicht verborgen oder verzerrt sind, ganz oder teilweise.
Die trackVisibility-Einstellung sagt dem Beobachter, Schnittstellen nur für Ziele zu melden, die der Browser nicht als visuell beeinträchtigt betrachtet, wie durch Änderung der Opazität oder durch Anwendung eines Filters oder einer Transformation.
Der Algorithmus ist konservativ und kann Elemente ausschließen, die technisch sichtbar sind, z.B. diejenigen mit nur einer leichten Opazitätsreduzierung.
Die Sichtbarkeitsberechnung ist rechenintensiv und sollte nur bei Bedarf verwendet werden.
Beim Verfolgen der Sichtbarkeit sollte auch eine delay festgelegt werden, um die minimale Berichtsperiode zu beschränken.
Die Empfehlung ist, dass Sie die Verzögerung auf den größten tolerierbaren Wert setzen (die Mindestverzögerung beim Verfolgen der Sichtbarkeit beträgt 100 Millisekunden).
Clipping und das Schnittstellenrechteck
Der Browser berechnet das finale Schnittstellen-Rechteck wie folgt; dies wird alles für Sie gemacht, aber es kann hilfreich sein, diese Schritte zu verstehen, um besser zu verstehen, wann Schnittstellen auftreten werden.
- Das Umrandungsrechteck des Zielelements (d.h. das kleinste Rechteck, das die Umrahmungen jedes Teils des Elements vollständig einschließt) wird durch Aufrufen von
getBoundingClientRect()beim Ziel erhalten. Dies ist das größte, das das Schnittstellenrechteck sein darf. Die verbleibenden Schritte entfernen Teile, die nicht schneiden. - Beginnend beim unmittelbaren übergeordneten Block und sich nach außen bewegend wird das Clipping (falls vorhanden) jedes umgebenden Blocks auf das Schnittstellen-Rechteck angewendet.
Das Clipping eines Blocks wird basierend auf der Schnittstelle der beiden Blöcke und dem Clipping-Modus (falls vorhanden) bestimmt, der durch die
overflow-Eigenschaft angegeben ist. Wennoverflowauf etwas anderes alsvisiblegesetzt ist, bewirkt dies, dass das Clipping auftritt. - Wenn eines der umgebenden Elemente die Wurzel eines verschachtelten Browser-Kontextes ist (wie das Dokument, das in einem
<iframe>enthalten ist), wird das Schnittstellen-Rechteck auf den Anzeigebereich des enthaltenden Kontexts geclippt, und die Rekursion aufwärts durch die Container wird mit dem enthaltenen Block des Containers fortgesetzt. Wenn also die oberste Ebene eines<iframe>erreicht wird, wird das Schnittstellen-Rechteck auf das Anzeigefenster des Frames geclippt, dann ist das übergeordnete Element des Frames der nächste Block, der zur Intersection-Root rekursiv verarbeitet wird. - Wenn die Rekursion aufwärts das Schnittstellen-Root erreicht, wird das resultierende Rechteck in den Koordinatenraum des Schnittstellen-Roots abgebildet.
- Das resultierende Rechteck wird dann aktualisiert, indem es mit dem root intersection rectangle geschnitten wird.
- Dieses Rechteck wird schließlich in den Koordinatenraum des
documentdes Ziels abgebildet.
Schnittstellen
IntersectionObserver-
Die primäre Schnittstelle für die Intersection Observer API. Bietet Methoden zum Erstellen und Verwalten eines Beobachters, der jede Anzahl von Zielelementen für dieselbe Schnittstellenkonfiguration beobachten kann. Jeder Beobachter kann asynchron Änderungen in der Schnittstelle zwischen einem oder mehreren Zielelementen und einem gemeinsamen Vorfahrenelement oder mit ihrem obersten
Documentviewportbeobachten. Der Vorfahre oder der Viewport wird als Root bezeichnet. IntersectionObserverEntry-
Beschreibt die Schnittstelle zwischen dem Zielelement und seinem Wurzelcontainer in einem bestimmten Übergangsmoment. Objekte dieses Typs können nur auf zwei Arten erhalten werden: als Eingabe für Ihren
IntersectionObserver-Callback oder durch Aufruf vonIntersectionObserver.takeRecords().
Ein einfaches Beispiel
Dieses einfache Beispiel bewirkt, dass sich ein Zielelement in seiner Farbe und Transparenz ändert, wenn es mehr oder weniger sichtbar wird. Bei Timing element visibility with the Intersection Observer API finden Sie ein ausführlicheres Beispiel, das zeigt, wie lange eine Reihe von Elementen (wie Anzeigen) für den Benutzer sichtbar sind, und auf diese Informationen reagieren, indem Sie Statistiken aufzeichnen oder Elemente aktualisieren.
HTML
Das HTML für dieses Beispiel ist sehr kurz und umfasst ein Primärelement, das die Box ist, auf die wir zielen werden (mit der kreativen ID "box") und einige Inhalte innerhalb der Box.
<div id="box">
<div class="vertical">Welcome to <strong>The Box!</strong></div>
</div>
CSS
Das CSS ist für die Zwecke dieses Beispiels nicht besonders wichtig; es legt das Element aus und stellt sicher, dass die background-color und border-Attribute an CSS-Übergängen teilnehmen können, die wir verwenden werden, um die Änderungen am Element zu beeinflussen, wenn es mehr oder weniger verdeckt wird.
#box {
background-color: rgb(40 40 190 / 100%);
border: 4px solid rgb(20 20 120);
transition:
background-color 1s,
border 1s;
width: 350px;
height: 350px;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.vertical {
color: white;
font: 32px "Arial";
}
.extra {
width: 350px;
height: 350px;
margin-top: 10px;
border: 4px solid rgb(20 20 120);
text-align: center;
padding: 20px;
}
JavaScript
Schließlich werfen wir einen Blick auf den JavaScript-Code, der die Intersection Observer API verwendet, um Dinge zu bewirken.
Vorbereiten
Zuerst müssen wir einige Variablen einrichten und den Beobachter installieren.
const numSteps = 20.0;
const boxElement = document.querySelector("#box");
let prevRatio = 0.0;
let increasingColor = "rgb(40 40 190 / ratio)";
let decreasingColor = "rgb(190 40 40 / ratio)";
createObserver();
Die Konstanten und Variablen, die wir hier einrichten, sind:
numSteps-
Eine Konstante, die angibt, wie viele Schwellenwerte wir zwischen einem Sichtbarkeitsverhältnis von 0,0 und 1,0 haben möchten.
prevRatio-
Diese Variable wird verwendet, um das Sichtbarkeitsverhältnis aufzuzeichnen, das beim letzten Überschreiten eines Schwellenwerts galt; dies ermöglicht es uns, herauszufinden, ob das Zielelement mehr oder weniger sichtbar wird.
increasingColor-
Eine Zeichenkette, die eine Farbe definiert, die wir auf das Zielelement anwenden, wenn das Sichtbarkeitsverhältnis steigt. Das Wort "ratio" in dieser Zeichenkette wird durch das aktuelle Sichtbarkeitsverhältnis des Ziels ersetzt, sodass sich nicht nur die Farbe ändert, sondern auch die Deckkraft des Ziels, wenn es weniger verdeckt wird.
decreasingColor-
Ähnlich ist dies eine Zeichenkette, die eine Farbe definiert, die wir anwenden, wenn das Sichtbarkeitsverhältnis sinkt.
Wir erhalten eine Referenz auf das Element mit der ID "box" mithilfe von querySelector(), rufen dann die createObserver()-Methode auf, die wir gleich erstellen werden, um den Aufbau und die Installation des Intersection Observers zu handhaben.
Erstellen des Intersection Observers
Die Methode createObserver() wird einmal nach dem Laden der Seite aufgerufen, um den neuen IntersectionObserver zu erstellen und den Vorgang des Beobachtens des Zielelements zu starten.
function createObserver() {
const options = {
root: null,
rootMargin: "0px",
threshold: buildThresholdList(),
};
const observer = new IntersectionObserver(handleIntersect, options);
observer.observe(boxElement);
}
Dies beginnt mit der Einrichtung eines options-Objekts, das die Einstellungen für den Observer enthält. Wir möchten Änderungen in der Sichtbarkeit des Zielelements im Verhältnis zum Viewport des Dokuments beobachten, daher ist root null. Wir brauchen keine Marge, daher wird der Margenoffset, rootMargin, auf "0px" festgelegt. Dies veranlasst den Observer, Änderungen der Schnittstelle zwischen den Begrenzungen des Zielelements und denen des Viewports ohne hinzugefügten (oder abgezogenen) Raum zu beobachten.
Die Liste der Schwellenwerte des Sichtbarkeitsverhältnisses, threshold, wird von der Funktion buildThresholdList() erstellt. Die Schwellenwertliste wird in diesem Beispiel programmiert erstellt, da es viele von ihnen gibt und die Anzahl anpassbar sein soll.
Sobald options bereit ist, erstellen wir den neuen Observer, indem wir den Konstruktor IntersectionObserver() aufrufen, eine Funktion angeben, die aufgerufen wird, wenn Schnittstellen einen unserer Schwellenwerte überschreiten, handleIntersect(), und unser Set von Optionen. Wir rufen dann observe() am zurückgegebenen Observer auf, und übergeben das gewünschte Zielelement.
Wir könnten uns entscheiden, mehrere Elemente für Schnittstellensichtbarkeitsänderungen im Verhältnis zum Viewport zu überwachen, indem wir observer.observe() für jedes dieser Elemente aufrufen, wenn wir dies tun möchten.
Erstellen des Arrays von Schwellenwert-Verhältnissen
Die Funktion buildThresholdList(), die die Liste der Schwellenwerte erstellt, sieht folgendermaßen aus:
function buildThresholdList() {
const thresholds = [];
const numSteps = 20;
for (let i = 1.0; i <= numSteps; i++) {
const ratio = i / numSteps;
thresholds.push(ratio);
}
thresholds.push(0);
return thresholds;
}
Dies erstellt das Array von Schwellenwerten – jedes von ihnen ist ein Verhältnis zwischen 0,0 und 1,0, indem es den Wert i/numSteps in das thresholds-Array für jedes Ganzzahl-i zwischen 1 und numSteps ersetzt. Es fügt auch die 0 hinzu, um diesen Wert einzuschließen. Das Ergebnis ergibt bei dem Standardwert von numSteps (20) folgende Liste von Schwellenwerten:
| # | Verhältnis | # | Verhältnis |
|---|---|---|---|
| 0 | 0.05 | 11 | 0.6 |
| 1 | 0.1 | 12 | 0.65 |
| 2 | 0.15 | 13 | 0.7 |
| 3 | 0.2 | 14 | 0.75 |
| 4 | 0.25 | 15 | 0.8 |
| 5 | 0.3 | 16 | 0.85 |
| 6 | 0.35 | 17 | 0.9 |
| 7 | 0.4 | 18 | 0.95 |
| 8 | 0.45 | 19 | 1 |
| 9 | 0.5 | 20 | 0 |
| 10 | 0.55 |
Wir könnten natürlich das Array von Schwellenwerten in unseren Code fest codieren, und oft werden Sie das auch tun. Aber dieses Beispiel lässt Raum für das Hinzufügen von Konfigurationselementen zur Anpassung der Granularität, zum Beispiel.
Umgang mit Schnittstellenänderungen
Wenn der Browser erkennt, dass das Zielelement (in unserem Fall das mit der ID "box") enthüllt oder verdeckt wurde, so dass sein Sichtbarkeitsverhältnis einen unserer Schwellenwerte überschreitet, ruft es unsere Handler-Funktion handleIntersect() auf:
function handleIntersect(entries, observer) {
entries.forEach((entry) => {
if (entry.intersectionRatio > prevRatio) {
entry.target.style.backgroundColor = increasingColor.replace(
"ratio",
entry.intersectionRatio,
);
} else {
entry.target.style.backgroundColor = decreasingColor.replace(
"ratio",
entry.intersectionRatio,
);
}
prevRatio = entry.intersectionRatio;
});
}
Für jedes IntersectionObserverEntry in der Liste entries, überprüfen wir, ob das intersectionRatio des Eintrags steigt; wenn dies der Fall ist, setzen wir die background-color des Ziels auf die Zeichenkette in increasingColor (denken Sie daran, dass es "rgb(40 40 190 / ratio)" ist), ersetzen das Wort "ratio" durch das intersectionRatio des Eintrags. Das Ergebnis: nicht nur ändert sich die Farbe, sondern auch die Transparenz des Zielelements; wenn das Schnittstellenverhältnis sinkt, sinkt auch der Alpha-Wert der Hintergrundfarbe mit und führt zu einem Element, das transparenter ist.
In ähnlicher Weise, wenn das intersectionRatio sinkt, verwenden wir die Zeichenkette decreasingColor und ersetzen das Wort "ratio" darin durch das intersectionRatio, bevor wir die background-color des Zielelements setzen.
Schließlich, um zu verfolgen, ob das Schnittstellenverhältnis steigt oder sinkt, merken wir uns das aktuelle Verhältnis in der Variable prevRatio.
Ergebnis
Unten ist das resultierende Inhaltsstück. Scrollen Sie diese Seite auf und ab und beobachten Sie, wie sich das Erscheinungsbild der Box dabei verändert.
Ein noch umfangreicheres Beispiel finden Sie unter Timing element visibility with the Intersection Observer API.
Spezifikationen
| Specification |
|---|
| Intersection Observer> # intersection-observer-interface> |