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

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

תמיכה בדפדפן

  • 51
  • 15
  • 55
  • 12.1

מקור

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

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

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

יחס צומת.

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

גלילה ב-div

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

שילוב של כל הפריטים!

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

גלילה מתמשכת

עדכונים נוספים בבקשה

כפי שצוין קודם, הקריאה החוזרת (callback) תופעל פעם אחת כשהרכיב שנמדד יוצג באופן חלקי, ופעם נוספת אחרי שהוא יצא מאזור התצוגה. כך מקבלים תשובה מ-IntersectionObserver לשאלה "האם רכיב X בתצוגה?". עם זאת, במקרים מסוימים ייתכן שזה לא יהיה מספיק.

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

אנימציית סף.

יש אפשרויות נוספות?

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

כמה עבודה אפשר לבצע בקריאה החוזרת?

תשובה קצרה ומתוקה: אם משקיעים יותר מדי זמן בקריאה החוזרת (callback), הם גורמים לעיכוב בעדכון האפליקציה — כל השיטות הנפוצות רלוונטיות.

המשך והצליב את הרכיבים שלך

תמיכת הדפדפן ב-IntersectionObserver טובה, כפי שהיא זמינה בכל הדפדפנים המתקדמים. אם יש צורך, אפשר להשתמש ב-polyfill בדפדפנים ישנים יותר, והוא זמין במאגר של WICG. כמובן שלא תיהנו מיתרונות הביצועים אם תשתמשו ב-polyfill שהטמעה מותאמת תעניק לכם.

אפשר להתחיל להשתמש ב-IntersectionObserver כבר עכשיו. ספרו לנו מה חשבתם.