Intersection Observer הוא אחד מאותם ממשקי API שסביר להניח שכולם אוהבים, ואפשר להשתמש בו בכל הדפדפנים הגדולים. מפתחים השתמשו ב-API הזה למגוון רחב של תרחישי שימוש, כולל טעינה עצלה של תמונות וסרטונים, התראות כשאלמנטים מגיעים ל-position: sticky, הפעלת אירועים של ניתוח נתונים ועוד.
בצורה הבסיסית ביותר, כך נראה API v1 של IntersectionObserver:
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'));
אתגרים שקשורים לניראות ב-Intersection Observer גרסה 1
בעזרת Intersection Observer v1 API, אפשר לדעת מתי רכיב מסוים נגלל אל אזור התצוגה של החלון. עם זאת, אי אפשר לקבוע אם הרכיב הזה מכוסה על ידי תוכן אחר בדף, תופעה שנקראת הסתרה, או אם הרכיב מוצג אחרי שינוי באמצעות CSS, כמו transform, opacity או filter, שיכולים להפוך את הרכיב לבלתי נראה.
כדי לקבוע את המידע הזה לגבי רכיב במסמך ברמה העליונה, אפשר לנתח את ה-DOM באמצעות JavaScript, למשל באמצעות DocumentOrShadowRoot.elementFromPoint().
לעומת זאת, אי אפשר להשיג את אותו המידע אם הרכיב הרלוונטי נמצא ב-iframe של צד שלישי.
למה הנראות חשובה?
לצערנו, יש באינטרנט גורמים זדוניים. לדוגמה, בעל תוכן דיגיטלי לא ישר יכול להשתמש במודעות מסוג תשלום לפי קליק באתר. הם עלולים להערים על משתמשים כדי שיקליקו על המודעות האלה כדי להרוויח יותר כסף, לפחות עד שרשת המודעות תגלה את התרמית. בדרך כלל, מודעות כאלה מוצגות ב-iframes.
כדי להטעות את המשתמשים, בעל האתר יכול להגדיר את מסגרות ה-iframe של המודעות כשקופות לחלוטין באמצעות CSS: iframe { opacity: 0; }. לאחר מכן, הם יכולים להציב את ה-iframe השקוף הזה מעל תוכן מושך, כמו סרטון חמוד של חתול, שהמשתמשים רוצים ללחוץ עליו.
הפעולה הזו נקראת הונאת קליקים.
אפשר לראות הדגמה של מתקפת קליקג'אקינג בחלק העליון של ההדגמה שלנו. נסו לצפות בסרטון של החתול ולהפעיל את מצב הטריק. המערכת רושמת קליקים על המודעה ב-iframe כקליקים לגיטימיים, גם אם לחצתם עליה (בטעות) בזמן שה-iframe היה שקוף.

שיפורים ב-Intersection Observer גרסה 2
Intersection Observer v2 יכול לעקוב אחרי ה'חשיפה' של רכיב כפי שאדם יגדיר אותה. אם מגדירים אפשרות ב-IntersectionObserver
constructor, המופעים שמתקבלים של IntersectionObserverEntry כוללים שדה בוליאני חדש בשם isVisible. כשהערך של isVisible
הוא true, הדפדפן מוודא שהרכיב לא מכוסה לחלוטין על ידי תוכן אחר, ואין לו אפקטים חזותיים שמסתירים או משנים את התצוגה שלו. אם הערך של isVisible הוא false, הדפדפן לא יכול לספק את ההבטחה הזו.
המפרט מאפשר פסילות שגויות: הערך של isVisible יכול להיות false גם כשהרכיב גלוי באמת ולא השתנה. לצורך ביצועים, הדפדפנים משתמשים בחישובים פשוטים יותר, כמו תיבות תוחמות וצורות מלבניות, ולא בודקים כל פיקסל לפרטים מורכבים כמו border-radius.
עם זאת, אסור בשום מקרה להציג תוצאות חיוביות מוטעות. המשמעות היא ש-isVisible לא יהיה true אם הרכיב לא גלוי לחלוטין ולא עבר שינוי.
החלת השינויים האלה
ה-constructor IntersectionObserver כולל עכשיו שתי מאפייני הגדרה נוספים:
-
delayהוא מספר שמציין את העיכוב המינימלי באלפיות השנייה בין ההתראות מהמשקיף, עבור יעד נתון. -
trackVisibilityהוא ערך בוליאני שמציין אם הצופה יעקוב אחרי שינויים בהרשאות הגישה של היעד.
אם הערך של trackVisibility הוא true, הערך של delay צריך להיות 100 או ערך גבוה יותר
(כלומר, לא יותר מהתראה אחת כל 100 אלפיות השנייה).
חישוב הנראות הוא יקר, ולכן זהו אמצעי זהירות מפני פגיעה בביצועים וצריכת הסוללה. מפתחים אחראיים צריכים להשתמש בערך ההשהיה הגדול ביותר שאפשר.
המאפיין,
מחשב את החשיפה. בדומה לגרסה 1, כשהמאפיין trackVisibility של רכיב ה-observer הוא false, רכיב היעד נחשב כגלוי
בגרסה 2, היעד נחשב כבלתי נראה אם:
יש לו מטריצת טרנספורמציה אפקטיבית, שאינה תרגום דו-ממדי או הגדלה דו-ממדית פרופורציונלית.
היעד או רכיב כלשהו בשרשרת הבלוקים שמכילה אותו, כוללים אטימות אפקטיבית שקטנה מ-1.0.
היעד או כל אלמנט בשרשרת הבלוקים שמכילה אותו כוללים מסננים.
אם ההטמעה לא יכולה להבטיח שהיעד לא מוסתר לחלוטין על ידי תוכן אחר בדף.
המשמעות היא שההטמעות הנוכחיות הן די שמרניות מבחינת הבטחת הנראות. לדוגמה, החלת מסנן גווני אפור שכמעט לא מורגש (filter: grayscale(0.01%)) או הגדרת השקיפות הכי נמוכה (opacity: 0.99) תגרום לכך שהרכיב יהיה בלתי נראה.
הנה קוד לדוגמה שממחיש את התכונות החדשות של ה-API. אפשר לראות את הלוגיקה של מעקב הקליקים בפעולה בחלק השני של ההדגמה. נסו לצפות בסרטון של הגור. מפעילים מצב הטעיה כדי להפוך את עצמכם לשחקן זדוני ולראות איך Intersection Observer v2 מונע מעקב אחרי קליקים לא לגיטימיים על מודעות. 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 v2, fallback 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'));
מקורות מידע נוספים
- טיוטה של Intersection Observer.
- Intersection Observer v2 בסטטוס הפלטפורמה של Chrome.
תודות
תודה ל-Simeon Vincent, Yoav Weiss ו-Mathias Bynens על הבדיקה, ול-Stefan Zager על הבדיקה וההטמעה של התכונה ב-Chrome.