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

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

תמיכה בדפדפן

  • 51
  • 15
  • 55
  • 12.1

מקור

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

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

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