אירועי IntersectionObserver מאפשרים לכם לדעת מתי רכיב שנצפה נכנס או יוצא מחלון התצוגה של הדפדפן.
נניח שאתם רוצים לעקוב אחרי הרגעים שבהם רכיב ב-DOM נכנס לאזור התצוגה הגלוי. יכול להיות שתרצו לעשות זאת כדי שתוכלו לטעון תמונות באופן איטי (lazy-load) בדיוק בזמן, או כי אתם צריכים לדעת אם המשתמש באמת מסתכל על באנר מודעה מסוים. אפשר לעשות זאת על ידי חיבור אירוע הגלילה או באמצעות טיימר תקופתי והפעלת getBoundingClientRect()
על הרכיב הזה.
עם זאת, הגישה הזו איטית מאוד, כי כל קריאה ל-getBoundingClientRect()
מאלצת את הדפדפן לסדר מחדש את כל הדף, וכתוצאה מכך האתר יהיה לא יציב. המצב הופך כמעט לבלתי אפשרי כשידוע שהאתר נטען בתוך iframe, ואתם רוצים לדעת מתי המשתמש יכול לראות רכיב. מודל המקור היחיד והדפדפן לא יאפשרו לכם לגשת לנתונים מדף האינטרנט שמכיל את ה-iframe. זוהי בעיה נפוצה, למשל, במודעות שנטענות לעיתים קרובות באמצעות iframe.
IntersectionObserver
תוכנן כדי לשפר את היעילות של בדיקת החשיפה הזו, והוא מופיע בכל הדפדפנים המודרניים. IntersectionObserver
מאפשר לכם לדעת מתי רכיב שנצפה נכנס או יוצא מחלון התצוגה של הדפדפן.

איך יוצרים IntersectionObserver
ה-API קטן למדי, והדרך הטובה ביותר לתאר אותו היא באמצעות דוגמה:
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();
אם משתמשים באפשרויות ברירת המחדל של IntersectionObserver
, פונקציית ה-callback תופעל גם כשהרכיב נכנס לטווח הראייה באופן חלקי וגם כשהוא יוצא ממנו לגמרי.
אם צריך לעקוב אחרי כמה רכיבים, אפשר גם מומלץ לעקוב אחרי כמה רכיבים באמצעות אותה מופע IntersectionObserver
, על ידי קריאה ל-observe()
כמה פעמים.
הפרמטר entries
מועבר ל-callback, שהוא מערך של אובייקטים מסוג IntersectionObserverEntry
. כל אובייקט כזה מכיל נתוני צומת מעודכנים של אחד מהרכיבים שנצפו.
🔽[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
היא התוצאה של קריאה ל-getBoundingClientRect()
ברכיב הבסיס, שהוא אזור התצוגה כברירת מחדל. boundingClientRect
היא התוצאה של getBoundingClientRect()
שנקרא על הרכיב שנצפה. intersectionRect
הוא הצומת של שני המלבנים האלה, והוא מראה איזה חלק של הרכיב שנצפה גלוי. המאפיין intersectionRatio
קשור מאוד למאפיין הקודם, והוא מציין כמה מהרכיב גלוי. בעזרת המידע הזה, עכשיו תוכלו להטמיע תכונות כמו טעינת נכסים בזמן אמת לפני שהם יהיו גלויים במסך. ביעילות.

IntersectionObserver
s מעבירים את הנתונים שלהם באופן אסינכררוני, וקוד ה-callback יפעל ב-thread הראשי. בנוסף, במפרט מצוין בפועל ש-IntersectionObserver
צריך להשתמש ב-requestIdleCallback()
. כלומר, הקריאה למספר החזרה שלכם תהיה בעדיפות נמוכה והדפדפן יבצע אותה במהלך זמן השהיה. זוהי החלטה מודעת של העיצוב.
גלילה של divs
אני לא אוהב לגלול בתוך אלמנט, אבל אני לא כאן כדי לשפוט, וגם IntersectionObserver
לא. האובייקט options
מקבל אפשרות root
שמאפשרת להגדיר חלופה למיקום הצפייה כשורש. חשוב לזכור ש-root
צריך להיות אב קדמון של כל הרכיבים שנצפו.
חותכים את כל הדברים!
לא! מפתח גרוע! זה לא שימוש מודע במחזורי המעבד של המשתמשים. ניקח לדוגמה גלילה אינסופית: בתרחיש כזה, מומלץ מאוד להוסיף חיישנים ל-DOM ולעקוב אחריהם (ולמחזר אותם!). צריך להוסיף גלאי קרוב לפריט האחרון בגלילה האינסופית. כשהחיישן הזה מופיע, אפשר להשתמש ב-callback כדי לטעון נתונים, ליצור את הפריטים הבאים, לצרף אותם ל-DOM ולהזיז את החיישן בהתאם. אם מחזירים את השומר לשימוש חוזר כראוי, אין צורך בקריאה נוספת ל-observe()
. ה-IntersectionObserver
ממשיך לפעול.

עוד עדכונים, בבקשה
כפי שצוין קודם, פונקציית ה-callback תופעל פעם אחת כשהרכיב שנצפה נכנס באופן חלקי לתצוגה, ופעם נוספת כשהוא יוצא מטווח התצוגה. כך הפונקציה IntersectionObserver
מספקת תשובה לשאלה "האם רכיב X נמצא בתצוגה?". עם זאת, בתרחישים לדוגמה מסוימים, יכול להיות שזה לא מספיק.
כאן נכנסת לתמונה האפשרות threshold
. הוא מאפשר להגדיר מערך של ערכי סף של intersectionRatio
. הקריאה החוזרת תתבצע בכל פעם ש-intersectionRatio
חוצה את אחד מהערכים האלה. ערך ברירת המחדל של threshold
הוא [0]
, ולכן זוהי התנהגות ברירת המחדל. אם נשנה את הערך של threshold
ל-[0, 0.25, 0.5, 0.75, 1]
, נקבל התראה בכל פעם שעוד רבע מהרכיב יהפוך לנגלה:

יש אפשרויות אחרות?
נכון לעכשיו, יש רק אפשרות נוספת לאפשרויות שצוינו למעלה. rootMargin
מאפשר לציין את השוליים של הבסיס, וכך להגדיל או לכווץ את האזור שמשמש למפגשים. השוליים האלה מצוינים באמצעות מחרוזת בסגנון CSS, כמו "10px 20px 30px 40px"
, שמציינת את השוליים העליון, הימני, התחתון והשמאלי, בהתאמה. לסיכום, המבנה של האפשרויות IntersectionObserver
מציע את האפשרויות הבאות:
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>
magic
אירועי IntersectionObserver
תוכננו במיוחד עבור שירותי מודעות וווידג'טים של רשתות חברתיות, שבהם נעשה שימוש לעיתים קרובות ברכיבי <iframe>
, ויכול להיות שיועילו מהמידע על כך שהם גלויים. אם <iframe>
מזהה אחד מהאלמנטים שלו, גלילה ב-<iframe>
וגלילה בחלון שמכיל את <iframe>
יפעילו את פונקציית ה-callback בזמנים המתאימים. עם זאת, במקרה השני, הערך של rootBounds
יוגדר כ-null
כדי למנוע דליפת נתונים בין מקורות.
מה IntersectionObserver
לא עוסק?
חשוב לזכור ש-IntersectionObserver
לא מיועד להציג תמונות ברזולוציה גבוהה או להציג נתונים בזמן אמת. שימוש בהם כדי להטמיע תכונות כמו אנימציות שתלובות בגלילה נכשל בוודאות, כי הנתונים יהיו – באופן מדויק – לא מעודכנים עד שתשתמשו בהם. הסרטון מכיל פרטים נוספים על התרחישים לדוגמה המקוריים של IntersectionObserver
.
כמה עבודה אפשר לבצע בשיחה החוזרת?
בקצרה: אם תימשכו את הזמן של הקריאה החוזרת יותר מדי, האפליקציה תתעכב – כל השיטות הנפוצות רלוונטיות.
קדימה, ערבבו את הרכיבים
התמיכה בדפדפנים ב-IntersectionObserver
טובה, כי היא זמינה בכל הדפדפנים המודרניים. במקרה הצורך, אפשר להשתמש ב-polyfill בדפדפנים ישנים יותר. ה-polyfill זמין במאגר של WICG. ברור שלא תקבלו את יתרונות הביצועים שמתקבלים מהטמעה ילידית באמצעות ה-polyfill הזה.
אפשר להתחיל להשתמש ב-IntersectionObserver
כבר עכשיו. נשמח לדעת מה המצאת.