Intersection Observer v2 aggiunge la capacità non solo di osservare le intersezioni in sé, ma anche di rileva se l'elemento che si interseca era visibile al momento dell'intersezione.
Intersection Observer v1 è una di quelle API probabilmente amati da tutti e ora che
È supportato anche da Safari,
è finalmente utilizzabile universalmente in tutti i principali browser. Per un rapido ripasso dell'API,
ti consiglio di guardare Surma
Micropunta super ricaricata sull'intersezione
Osservatore v1 incorporato di seguito.
Puoi anche leggere gli approfondimenti di Surma
articolo.
Gli utenti hanno utilizzato Intersection Observer v1 per un'ampia gamma di casi d'uso, come
caricamento lento di immagini e video,
ricevere notifiche quando gli elementi raggiungono position: sticky
,
di attivare eventi di analisi,
e molto altro ancora.
Per i dettagli completi, consulta Documentazione di Intersection Observer su MDN ma ti ricordiamo che questo è l'aspetto dell'API Intersection Observer v1 nella maggior parte dei casi. richiesta di base:
const onIntersection = (entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
console.log(entry);
}
}
};
const observer = new IntersectionObserver(onIntersection);
observer.observe(document.querySelector('#some-target'));
Quali problemi sono presenti nella versione 1 di Intersection Observer?
Precisiamo che Intersection Observer v1 è ottimo, ma non perfetto. Esistono
i casi in cui l'API non è all'altezza. Diamo un'occhiata più da vicino.
L'API Intersection Observer v1 può indicare quando un elemento viene fatto scorrere verso il
l'area visibile della finestra, ma non indica se l'elemento è coperto
da qualsiasi altro contenuto della pagina (vale a dire, quando l'elemento è occulto) o dal fatto che
la visualizzazione visiva dell'elemento è stata modificata da effetti visivi come transform
, opacity
,
filter
e così via, che possono renderli efficaci visibili.
Per un elemento del documento di primo livello, queste informazioni possono essere determinate analizzando
il DOM tramite JavaScript, ad esempio
DocumentOrShadowRoot.elementFromPoint()
per poi andare più a fondo.
Al contrario, le stesse informazioni non possono essere ottenute se l'elemento in questione è
in un iframe di terze parti.
Perché la visibilità effettiva è così importante?
Sfortunatamente, Internet è un luogo che attira malintenzionati con intenzioni peggiori.
Ad esempio, un publisher losco che pubblica annunci pay-per-click su un sito di contenuti potrebbe essere incentivato
per indurre con l'inganno le persone a fare clic sui propri annunci e aumentare il pagamento dell'annuncio al publisher (almeno
per un breve periodo di tempo, fino a quando
la rete pubblicitaria non li individua).
Generalmente, questi annunci vengono pubblicati in iframe.
Se il publisher volesse convincere gli utenti a fare clic su tali annunci, potrebbe creare iframe
assolutamente trasparente, applicando una regola CSS iframe { opacity: 0; }
e sovrapponendo gli iframe
su qualcosa di accattivante, ad esempio un grazioso video di gatti su cui gli utenti vorrebbero davvero fare clic.
Questa pratica è chiamata clickjacking.
Puoi vedere un attacco clickjacking in azione nella sezione superiore di questo
demo (prova a "guardare" il video dei gatti)
e attivare la "modalità trucco").
Noterai che l'annuncio nell'iframe "pensa" ha ricevuto clic legittimi, anche se
in modo completamente trasparente quando gli utenti fanno (fingete involontariamente) di fare clic su di essi.
In che modo può risolvere il problema tramite Intersection Observer v2?
Intersection Observer v2 introduce il concetto di monitoraggio della "visibilità" effettiva di un target
elemento definito da un essere umano.
Impostando un'opzione nella sezione
costruttore IntersectionObserver
,
intersezione
IntersectionObserverEntry
conterrà un nuovo campo booleano denominato isVisible
.
Un valore true
di isVisible
è una solida garanzia dell'implementazione sottostante
che l'elemento target sia completamente libero da altri contenuti.
e non vengono applicati effetti visivi che alterano o distorceno la visualizzazione sullo schermo.
Al contrario, un valore false
significa che l'implementazione non può garantire questa garanzia.
Un dettaglio importante
specifiche
è che l'implementazione è consentita a segnalare falsi negativi (ovvero, l'impostazione di isVisible
a false
anche quando l'elemento target è completamente visibile e non modificato).
Per motivi di prestazioni o per altri motivi, i browser si limitano a lavorare con i limiti
scatole e geometria rettilinea; per cui non cercano di ottenere risultati perfetti
modifiche come border-radius
.
Detto ciò, i falsi positivi non sono consentiti in alcuna circostanza (ovvero, quando si imposta
isVisible
a true
quando l'elemento target non è completamente visibile e non è stato modificato).
Come si presenta il nuovo codice in pratica?
Il costruttore IntersectionObserver
ora richiede due proprietà di configurazione aggiuntive: delay
e trackVisibility
.
Il delay
è un numero che indica il ritardo minimo in millisecondi tra le notifiche da
l'osservatore per un dato bersaglio.
trackVisibility
è un valore booleano che indica se l'osservatore terrà traccia delle variazioni nel
visibilità.
È importante notare qui che quando trackVisibility
è true
, è necessario che delay
si trovi a
almeno 100
(ovvero non più di una notifica ogni 100 ms).
Come osservato in precedenza, il calcolo della visibilità è costoso e questo requisito è una precauzione contro
delle prestazioni e il consumo della batteria. Lo sviluppatore responsabile utilizzerà
il maggiore valore tollerabile per il ritardo.
In base all'attuale spec, la visibilità è calcolato come segue:
Se l'attributo
trackVisibility
dell'osservatore èfalse
, il target è considerato visibile. Corrisponde al comportamento attuale della versione 1.Se il target ha una matrice di trasformazione efficace diversa da una traduzione 2D o 2D proporzionale, il target è considerato invisibile.
Se il target, o qualsiasi elemento nella catena di blocchi che la contiene, ha un'opacità effettiva diversa da 1,0, il target è considerato invisibile.
Se al target, o a qualsiasi elemento nella catena di blocchi che la contiene, sono applicati filtri, il target è considerato invisibile.
Se l'implementazione non può garantire che il target sia completamente ignorato da un'altra pagina contenuti, il target è considerato invisibile.
Ciò significa che le implementazioni attuali sono piuttosto prudenti e garantiscono la visibilità.
Ad esempio, l'applicazione di un filtro scala di grigi quasi impercettibile come filter: grayscale(0.01%)
oppure l'impostazione di una trasparenza quasi invisibile con opacity: 0.99
viene eseguito il rendering dell'elemento
invisibile.
Di seguito è riportato un breve esempio di codice che illustra le nuove funzionalità dell'API. Puoi vedere il monitoraggio dei clic la logica in azione nella seconda sezione della demo (ma ora prova a "guardare" il video del cucciolo). Non dimenticare di attivare la "modalità trucco" da nuovo a immediatamente convertiti in un publisher losco e scopri come Intersection Observer v2 impedisce il tracciamento di clic sugli annunci non legittimi. Questa volta ci pensa Intersection Observer v2! 🎉
<!DOCTYPE html>
<!-- This is the ad running in the iframe -->
<button id="callToActionButton">Buy now!</button>
// This is code running in the iframe.
// The iframe must be visible for at least 800ms prior to an input event
// for the input event to be considered valid.
const minimumVisibleDuration = 800;
// Keep track of when the button transitioned to a visible state.
let visibleSince = 0;
const button = document.querySelector('#callToActionButton');
button.addEventListener('click', (event) => {
if ((visibleSince > 0) &&
(performance.now() - visibleSince >= minimumVisibleDuration)) {
trackAdClick();
} else {
rejectAdClick();
}
});
const observer = new IntersectionObserver((changes) => {
for (const change of changes) {
// ⚠️ Feature detection
if (typeof change.isVisible === 'undefined') {
// The browser doesn't support Intersection Observer v2, falling back to v1 behavior.
change.isVisible = true;
}
if (change.isIntersecting && change.isVisible) {
visibleSince = change.time;
} else {
visibleSince = 0;
}
}
}, {
threshold: [1.0],
// 🆕 Track the actual visibility of the element
trackVisibility: true,
// 🆕 Set a minimum delay between notifications
delay: 100
}));
// Require that the entire iframe be visible.
observer.observe(document.querySelector('#ad'));
Link correlati
- Bozza dell'editor più recente di Specifiche dell'osservatore di intersezione.
- Osservatore incroci v2 attivato Stato della piattaforma Chrome.
- Bug di Chromium Intersection Observer v2.
- Luce lampeggiante Intento di implementare la pubblicazione.
Ringraziamenti
Grazie a Simeon Vincent, Yoav Weiss e Mathias Bynens per leggere questo articolo e anche Stefan Zager per esaminare e implementare la funzionalità in Chrome. Immagine hero di Sergey Semin su Unsplash.