שרתי IntersectionObservers מודיעים לך כשרכיב שנצפה נכנס לאזור התצוגה של הדפדפן או יוצא ממנו.
נניח שאתם רוצים לעקוב אחרי מקרים שבהם רכיב ב-DOM נכנס לאזור התצוגה הגלוי. מומלץ לעשות זאת כדי לבצע טעינה מדורגת של תמונות בדיוק בזמן, או כדי לדעת אם המשתמש מביט בפועל בבאנר מסוים של מודעה. אפשר לעשות זאת על ידי חיבור אירוע הגלילה או על ידי שימוש בטיימר תקופתי וקריאה ל-getBoundingClientRect()
ברכיב הזה.
עם זאת, גישה זו איטית מאוד מכיוון שכל קריאה ל-getBoundingClientRect()
מאלצת את הדפדפן לפרוס מחדש את הדף כולו ולגרום ל-jank משמעותי לאתר שלך. עניינים כמעט בלתי אפשריים כאשר יודעים שהאתר נטען בתוך 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
, הקריאה החוזרת תיקרא גם כשהאלמנט יוצג חלקית וגם כשהוא יוצא לגמרי מאזור התצוגה.
אם אתם צריכים לצפות במספר רכיבים, אפשר ומומלץ גם לצפות במספר רכיבים באמצעות אותו מופע של IntersectionObserver
על ידי קריאה ל-observe()
כמה פעמים.
פרמטר entries
מועבר אל הקריאה החוזרת, שהוא מערך של אובייקטים מסוג 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
מעבירים את הנתונים שלהם באופן אסינכרוני, וקוד הקריאה החוזרת (callback) יפעל ב-thread הראשי. בנוסף, לפי המפרט מצוין שהטמעות של IntersectionObserver
צריכות להשתמש ב-requestIdleCallback()
. כלומר, הקריאה החוזרת שסיפקתם היא בעדיפות נמוכה ותבוצע על ידי הדפדפן במהלך זמן חוסר פעילות. זוהי החלטה מודעת של העיצוב.
גלילה divs
אני לא חובבת גלילה בתוך אלמנט, אבל אני לא כאן כדי לשפוט, וגם לא IntersectionObserver
. האובייקט options
מקבל אפשרות root
שמאפשרת להגדיר חלופה לאזור התצוגה בתור הבסיס. חשוב לזכור שהרכיב root
צריך להיות ישות אב של כל האלמנטים המתועדים.
מצטלבים בין כל הדברים!
לא. מפתח גרוע! שימוש לרעה במחזורי המעבד (CPU) של המשתמש. ניקח לדוגמה גולל אינסופי: במקרה הזה, בהחלט מומלץ להוסיף ל-DOM sentinels ולצפות בהם (ולמחזר!). כדאי להוסיף סנטינל קרוב לפריט האחרון בסרגל הגלילה האינסופי. כשהסנטinel מופיע, תוכלו להשתמש בקריאה החוזרת (callback) כדי לטעון נתונים, ליצור את הפריטים הבאים, לצרף אותם ל-DOM ולמקם אותם מחדש בהתאם. אם אין צורך למחזר את סנטינל כמו שצריך, אין צורך בשיחה נוספת אל observe()
. השיטה IntersectionObserver
ממשיכה לפעול.
עוד עדכונים
כפי שצוין קודם, הקריאה החוזרת (callback) תופעל פעם אחת כשהרכיב שנצפה יוצג באופן חלקי ופעם אחרת אחרי שהוא יוצא מאזור התצוגה. כך מקבלים תשובה מ-IntersectionObserver
לשאלה "האם הרכיב X מוצג?". עם זאת, במקרים מסוימים ייתכן שזה לא יהיה מספיק.
כאן נכנסת לתמונה האפשרות threshold
. היא מאפשרת להגדיר מערך של ספים מסוג intersectionRatio
. הקריאה החוזרת שלך תבוצע בכל פעם ש-intersectionRatio
יעבור אחד מהערכים האלה. ערך ברירת המחדל של threshold
הוא [0]
, שמסבירה את התנהגות ברירת המחדל. אם נשנה את ההגדרה threshold
ל-[0, 0.25, 0.5, 0.75, 1]
, נשלח לנו הודעה בכל פעם שרבעון נוסף של הרכיב יוצג למשתמשים:
יש אפשרויות נוספות?
נכון לעכשיו, יש רק אפשרות אחת נוספת לאפשרויות שצוינו למעלה. הפקודה rootMargin
מאפשרת לציין את השוליים של הבסיס, וכך מאפשרת למעשה להגדיל או לכווץ את השטח שמשמש לצמתים. השוליים האלה מצוינים באמצעות מחרוזת בסגנון CSS, ála "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>
נכסים מסוג IntersectionObserver
תוכננו במיוחד תוך מחשבה על שירותי מודעות וווידג'טים של רשתות חברתיות, שנעשה בהם שימוש לעיתים קרובות באלמנטים של <iframe>
ויכול להיות שהם יוכלו לדעת אם ניתן לראות אותם. אם <iframe>
מזהה את אחד מהאלמנטים שלו, גלילה ב-<iframe>
וגם גלילה בחלון שמכיל את ה-<iframe>
יפעילו את הקריאה החוזרת במועדים המתאימים. עם זאת, במקרה השני, הערך של rootBounds
יוגדר בתור null
כדי למנוע דליפה של נתונים בין מקורות.
במה IntersectionObserver
לא?
כדאי לזכור ש-IntersectionObserver
אינו מושלם באופן מכוון באמצעות פיקסל ואין זמן אחזור קצר. השימוש בהם ליישום מאמצים כגון אנימציות התלויות בגלילה עלול להיכשל, מכיוון שהנתונים כבר לא יהיו עדכניים עד לזמן שבו תשתמשו בהם. למסביר יש פרטים נוספים על תרחישי השימוש המקוריים ב-IntersectionObserver
.
כמה עבודה אפשר לעשות בהתקשרות החוזרת?
קצר ולעניין: אם תקדישו יותר מדי זמן בהתקשרות החוזרת, תיתכן השהיה באפליקציה — כל השיטות הנפוצות חלות.
קדימה ומצטלבים בין האלמנטים שלך
התמיכה בדפדפן IntersectionObserver
טובה, שהיא זמינה בכל הדפדפנים המודרניים. אם יש צורך, ניתן להשתמש ב-Polyfill בדפדפנים ישנים יותר, והוא זמין במאגר WICG. כמובן שלא תקבלו את יתרונות הביצועים באמצעות ה-Polyfill שאפשר לקבל מיישום מותאם.
אפשר להתחיל להשתמש ב-IntersectionObserver
כבר עכשיו! נשמח לשמוע מה חשבת.