IntersectionObserver' กำลังปรากฏตัว

IntersectionObservers จะแจ้งให้คุณทราบเมื่อองค์ประกอบที่พบเข้าหรือออกจากวิวพอร์ตของเบราว์เซอร์

การรองรับเบราว์เซอร์

  • Chrome: 51.
  • ขอบ: 15
  • Firefox: 55
  • Safari: 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() ในองค์ประกอบรูทซึ่งเป็นวิวพอร์ตโดยค่าเริ่มต้น boundingClientRect เป็นผลลัพธ์ของ getBoundingClientRect() ที่มีการเรียกใช้ในองค์ประกอบที่พบ intersectionRect คือจุดร่วมของสี่เหลี่ยม 2 รูปนี้ และบอกคุณว่าส่วนใดขององค์ประกอบที่พบนั้นสามารถมองเห็นได้อย่างมีประสิทธิภาพ intersectionRatio เกี่ยวข้องกันอย่างใกล้ชิดและบอกคุณว่าองค์ประกอบที่มองเห็นได้มากน้อยเพียงใด เมื่อมีข้อมูลนี้ คุณจะสามารถใช้งานฟีเจอร์ต่างๆ เช่น การโหลดเนื้อหาในเวลาเดียวก่อนที่เนื้อหาจะแสดงบนหน้าจอ อย่างมีประสิทธิภาพ

อัตราส่วนสี่แยก

IntersectionObserver จะส่งข้อมูลแบบไม่พร้อมกันและโค้ด Callback จะทำงานในเทรดหลัก นอกจากนี้ ข้อกำหนดยังระบุด้วยว่าการติดตั้งใช้งาน IntersectionObserver ควรใช้ requestIdleCallback() ซึ่งหมายความว่าการติดต่อกลับที่คุณให้มาจะมีลำดับความสำคัญต่ำและจะดำเนินการโดยเบราว์เซอร์ในระหว่างที่ไม่มีความเคลื่อนไหว นี่คือการตัดสินใจออกแบบอย่างรอบคอบ

div แบบเลื่อน

ไม่ค่อยชอบเลื่อนในองค์ประกอบเท่าไร ก็ไม่ได้อยากตัดสินและ IntersectionObserver ก็เช่นกัน ออบเจ็กต์ options จะใช้ตัวเลือก root ที่ช่วยให้คุณกำหนดทางเลือกอื่นแทนวิวพอร์ตเป็นรูทของคุณ โปรดทราบว่า root ต้องเป็นระดับบนขององค์ประกอบที่พบทั้งหมด

ตัดทุกสิ่งให้หมด!

ไม่เอาด้วยหรอก นักพัฒนาซอฟต์แวร์ไม่เก่ง! การทำเช่นนี้ไม่ได้คำนึงถึงการใช้งานรอบ CPU ของผู้ใช้ ลองนึกถึงแถบเลื่อนได้ไม่รู้จบเป็นตัวอย่าง ในสถานการณ์ดังกล่าว เราแนะนำให้เพิ่ม sentinels ลงใน DOM และสังเกต (และรีไซเคิล!) เหล่านั้น คุณควรเพิ่มคำสังเกตใกล้กับรายการสุดท้ายในการเลื่อนได้ไม่รู้จบ เมื่อผู้ฟังเห็น คุณสามารถใช้ Callback เพื่อโหลดข้อมูล สร้างรายการถัดไป แนบรายการดังกล่าวกับ DOM และเปลี่ยนตำแหน่งคำสังเกตให้สอดคล้องกัน หากนำผู้ดูแลกลับมาใช้ใหม่อย่างถูกต้อง ก็ไม่จำเป็นต้องโทรหา observe() เพิ่มเติม IntersectionObserver ยังคงทำงานต่อไป

ตัวเลื่อนได้ไม่รู้จบ

โปรดติดตามข้อมูลอัปเดตเพิ่มเติม

ดังที่กล่าวไว้ก่อนหน้านี้ การเรียกกลับจะทริกเกอร์ 1 ครั้งเมื่อองค์ประกอบที่สังเกตพบเห็นได้บางส่วน และอีกครั้งเมื่อออกจากวิวพอร์ต วิธีนี้จะทำให้ IntersectionObserver ตอบคำถามที่ว่า "มองเห็นองค์ประกอบ X อยู่ไหม" อย่างไรก็ตาม ในบาง Use Case อาจไม่เพียงพอ

เราจึงเลือกใช้ตัวเลือก threshold ซึ่งจะช่วยให้คุณกำหนดอาร์เรย์ของเกณฑ์ intersectionRatio ได้ ระบบจะเรียกการติดต่อกลับของคุณทุกครั้งที่ intersectionRatio ข้ามค่าใดค่าหนึ่งเหล่านี้ ค่าเริ่มต้นสำหรับ threshold คือ [0] ซึ่งอธิบายลักษณะการทำงานเริ่มต้น หากเราเปลี่ยน threshold เป็น [0, 0.25, 0.5, 0.75, 1] เราจะได้รับแจ้งทุกครั้งที่มีการเห็นองค์ประกอบอีก 1 ใน 4 ส่วน

ภาพเคลื่อนไหวของเกณฑ์

มีตัวเลือกอื่นๆ อีกไหม

ขณะนี้ มีตัวเลือกเพิ่มเติมเพียง 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>

IntersectionObserver ออกแบบมาโดยคำนึงถึงบริการโฆษณาและวิดเจ็ตโซเชียลเน็ตเวิร์กโดยเฉพาะ ซึ่งใช้องค์ประกอบ <iframe> อยู่บ่อยครั้งและจะได้รับประโยชน์จากการทราบว่าตนอยู่ในการแสดงผลหรือไม่ หาก <iframe> สังเกตเห็นองค์ประกอบใดองค์ประกอบหนึ่ง ทั้งการเลื่อน <iframe> และการเลื่อนหน้าต่างที่มี <iframe> จะทริกเกอร์ Callback ในเวลาที่เหมาะสม แต่ในกรณีหลัง ระบบจะตั้งค่า rootBounds เป็น null เพื่อหลีกเลี่ยงการรั่วไหลของข้อมูลข้ามต้นทาง

IntersectionObserver ไม่ได้เกี่ยวกับอะไร

โปรดทราบว่า IntersectionObserver ไม่ได้เจตนาให้พิกเซลสมบูรณ์แบบและไม่มีเวลาในการตอบสนองต่ำ การใช้โมเดลดังกล่าวเพื่อใช้งานด้านต่างๆ เช่น ภาพเคลื่อนไหวที่เป็นแบบเลื่อนได้จึงจะล้มเหลว เนื่องจากข้อมูลจะไม่อัปเดต (บอกมาตรงๆ) เมื่อถึงเวลาที่คุณจะใช้งาน คำอธิบายมีรายละเอียดเพิ่มเติมเกี่ยวกับกรณีการใช้งานเดิมสำหรับ IntersectionObserver

ฉันสามารถทำได้มากเพียงใดในการโทรกลับ

ไม่มากไม่น้อย: การใช้เวลาใน Callback มากเกินไปจะทำให้แอปล่าช้า - เป็นไปตามแนวทางปฏิบัติทั่วไปทั้งหมด

เดินออกไปและตัดธาตุของคุณออก

การรองรับเบราว์เซอร์ IntersectionObserver นั้นอยู่ในระดับดี เนื่องจากมีให้ใช้งานในเบราว์เซอร์รุ่นใหม่ทั้งหมด หากจำเป็น คุณสามารถใช้ Polyfill ในเบราว์เซอร์รุ่นเก่าและมีอยู่ในที่เก็บของ WICG แน่นอนว่าคุณจะไม่ได้รับประโยชน์ด้านประสิทธิภาพจากการใช้ Polyfill เหมือนมาจากการใช้งานแบบเนทีฟ

คุณสามารถเริ่มใช้ IntersectionObserver ได้ทันที บอกเราว่าคุณคิดเห็นอย่างไร