ממשקי IntersectionObservers מאפשרים לכם לקבל התראות כשרכיב שנמדד נכנס לאזור התצוגה של הדפדפן או יוצא ממנו.
נניח שאתם רוצים לעקוב אחרי הרגעים שבהם רכיב ב-DOM נכנס לאזור התצוגה הגלוי. יכול להיות שתרצו לעשות זאת כדי שתוכלו לטעון תמונות באופן איטי בזמן אמת, או כי אתם צריכים לדעת אם המשתמש באמת צופה בבאנר מודעה מסוים. אפשר לעשות זאת על ידי חיבור אירוע הגלילה או באמצעות טיימר תקופתי והפעלת getBoundingClientRect()
ברכיב הזה.
עם זאת, הגישה הזו איטית מאוד כי כל קריאה ל-getBoundingClientRect()
מאלצת את הדפדפן לפרוס מחדש את הדף כולו ועלולה לגרום לבעיות רבות באתר שלך. כאשר יודעים שהאתר נטען בתוך iframe ורוצים לדעת מתי המשתמש יכול לראות רכיב, כמעט בלתי אפשרי. מודל המקור היחיד והדפדפן לא יאפשרו לכם לגשת לנתונים מדף האינטרנט שמכיל את ה-iframe. זוהי בעיה נפוצה במודעות, למשל, שנטענות לעיתים קרובות באמצעות iframes.
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()
ברכיב הבסיסי (root), שהוא אזור התצוגה כברירת מחדל. boundingClientRect
היא התוצאה של getBoundingClientRect()
שנקרא על הרכיב שנצפה. intersectionRect
הוא החיתוך של שני המלבנים האלה ומראה בפועל איזה חלק של הרכיב שנמדד גלוי. המאפיין intersectionRatio
קשור מאוד למאפיין הקודם, והוא מראה כמה מהרכיב גלוי. בעזרת המידע הזה, תוכלו להטמיע תכונות כמו טעינת נכסים בזמן אמת לפני שהם יהיו גלויים במסך. ביעילות.
IntersectionObserver
s מעבירים את הנתונים שלהם באופן אסינכררוני, וקוד ה-callback יפעל ב-thread הראשי. בנוסף, במפרט מצוין בפועל שצריך להשתמש ב-requestIdleCallback()
בהטמעות של IntersectionObserver
. המשמעות היא שהקריאה ל-callback שסיפקתם תהיה בעדיפות נמוכה והדפדפן יבצע אותה במהלך זמן השהיה. זוהי החלטה מודעת לגבי העיצוב.
גלילה של divs
אני לא אוהב לגלול בתוך אלמנט, אבל אני לא כאן כדי לשפוט, וגם IntersectionObserver
לא. האובייקט options
מקבל אפשרות root
שמאפשרת להגדיר חלופה ל-viewport כשורש. חשוב לזכור ש-root
צריך להיות אב קדמון של כל הרכיבים שנצפו.
חותכים את כל הדברים!
לא! מפתח גרוע! זה לא שימוש מכוון במחזורי המעבד של המשתמש. ניקח לדוגמה גלילה אינסופית: בתרחיש כזה, מומלץ מאוד להוסיף חיישנים ל-DOM ולעקוב אחריהם (ולמחזר אותם!). צריך להוסיף סנטינל קרוב לפריט האחרון בגלילה האינסופית. כשהסנטינל מוצג, אפשר להשתמש בקריאה חוזרת (callback) כדי לטעון נתונים, ליצור את הפריטים הבאים, לצרף אותם ל-DOM ולמקם אותם מחדש בהתאם. אם ממחזרים את הסנטינל בצורה תקינה, אין צורך בקריאה נוספת ל-observe()
. IntersectionObserver
ממשיך לעבוד.
עוד עדכונים, בבקשה
כפי שצוין קודם, פונקציית ה-callback תופעל פעם אחת כשהאלמנט שנצפה נכנס באופן חלקי לתצוגה, ופעם נוספת כשהוא יוצא מטווח התצוגה. כך, IntersectionObserver
נותן תשובה לשאלה "האם רכיב X גלוי?". עם זאת, בתרחישים לדוגמה מסוימים, יכול להיות שזה לא מספיק.
כאן נכנסת לתמונה האפשרות threshold
. היא מאפשרת להגדיר מערך של ערכי סף של intersectionRatio
. הקריאה החוזרת (callback) תתבצע בכל פעם ש-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
.
כמה עבודה אפשר לבצע בשיחת החזרה?
תשובה קצרה ומתוקה: אם משקיעים יותר מדי זמן בקריאה החוזרת (callback), הם גורמים לעיכוב בעדכון האפליקציה — כל השיטות הנפוצות רלוונטיות.
המשך והצליב את הרכיבים שלך
התמיכה בדפדפנים ב-IntersectionObserver
טובה, כי היא זמינה בכל הדפדפנים המודרניים. במקרה הצורך, אפשר להשתמש ב-polyfill בדפדפנים ישנים יותר. ה-polyfill זמין במאגר של WICG. כמובן שלא תרוויחו את היתרונות מהביצועים עם ה-polyfill שניתן לכם באמצעות הטמעה מותאמת.
אפשר להתחיל להשתמש ב-IntersectionObserver
כבר עכשיו. נשמח לדעת מה המצאת.