אירועי IntersectionObserver מאפשרים לכם לדעת מתי רכיב שנצפה נכנס או יוצא מחלון התצוגה של הדפדפן.
נניח שאתם רוצים לעקוב אחרי הרגעים שבהם רכיב ב-DOM נכנס לאזור התצוגה הגלוי. יכול להיות שתרצו לעשות זאת כדי שתוכלו לטעון תמונות באופן איטי (lazy load) בדיוק בזמן, או כי אתם צריכים לדעת אם המשתמש באמת צופה בבאנר מודעה מסוים. אפשר לעשות זאת על ידי חיבור אירוע הגלילה או באמצעות טיימר תקופתי והפעלת 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()
ברכיב הבסיס, שהוא אזור התצוגה כברירת מחדל. 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
. הקריאה החוזרת תתבצע בכל פעם ש-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
כבר עכשיו. נשמח לדעת מה המצאת.