נכנסים לתצוגה של IntersectionObserver

ממשקי IntersectionObservers מאפשרים לכם לקבל התראות כשרכיב שנמדד נכנס לאזור התצוגה של הדפדפן או יוצא ממנו.

תמיכה בדפדפנים

  • Chrome: 51.
  • Edge:‏ 15.
  • Firefox: 55.
  • Safari: 12.1.

מקור

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

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

IntersectionObserver תוכנן כדי לשפר את היעילות של בדיקת החשיפה הזו, והוא זמין בכל הדפדפנים המודרניים. IntersectionObserver מאפשר לכם לדעת מתי רכיב שנצפה נכנס או יוצא מחלון התצוגה של הדפדפן.

היקף החשיפה של iframe

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

יחס הצטלבות.

IntersectionObservers מעבירים את הנתונים שלהם באופן אסינכררוני, וקוד ה-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 כבר עכשיו. נשמח לדעת מה המצאת.