IntersectionObserver จะแจ้งให้คุณทราบเมื่อองค์ประกอบที่สังเกตได้เข้าสู่หรือออกจากวิวพอร์ตของเบราว์เซอร์
สมมติว่าคุณต้องการติดตามเมื่อองค์ประกอบใน DOM เข้าสู่วิวพอร์ตที่มองเห็นได้ คุณอาจต้องการทําเช่นนี้เพื่อให้โหลดรูปภาพแบบ Lazy Load ได้ทันเวลา หรือเพราะคุณต้องทราบว่าผู้ใช้กําลังดูแบนเนอร์โฆษณาบางรายการอยู่หรือไม่ ซึ่งทำได้โดยการต่อเหตุการณ์การเลื่อนหรือใช้ตัวจับเวลาตามรอบและเรียกใช้ getBoundingClientRect()
ในองค์ประกอบนั้น
อย่างไรก็ตาม วิธีการนี้ช้ามากเนื่องจากการเรียก getBoundingClientRect()
แต่ละครั้งจะบังคับให้เบราว์เซอร์จัดเรียงหน้าเว็บใหม่ทั้งหมดและจะทำให้เว็บไซต์กระตุกอย่างมาก ปัญหาจะยิ่งทวีความซับซ้อนมากขึ้นเมื่อคุณทราบว่าเว็บไซต์กำลังโหลดภายใน iframe และต้องการทราบว่าผู้ใช้จะเห็นองค์ประกอบเมื่อใด รูปแบบต้นทางเดียวและเบราว์เซอร์จะไม่อนุญาตให้คุณเข้าถึงข้อมูลจากหน้าเว็บที่มี iframe ปัญหานี้พบได้ทั่วไปในโฆษณาที่โหลดโดยใช้ iframe บ่อยครั้ง
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
ไปยังการเรียกกลับ ซึ่งเป็นอาร์เรย์ของออบเจ็กต์ 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
จะส่งข้อมูลแบบไม่พร้อมกัน และโค้ดการเรียกกลับจะทํางานในเธรดหลัก นอกจากนี้ ข้อกำหนดยังระบุว่าการติดตั้งใช้งาน IntersectionObserver
ควรใช้ requestIdleCallback()
ซึ่งหมายความว่าการเรียกใช้การเรียกกลับที่คุณระบุจะมีลำดับความสำคัญต่ำและเบราว์เซอร์จะเป็นผู้ดำเนินการในระหว่างที่ไม่ได้ใช้งาน นี่เป็นการตัดสินใจด้านการออกแบบอย่างมีสติ
div แบบเลื่อน
เราไม่ค่อยชอบการเลื่อนภายในองค์ประกอบ แต่ไม่ได้ตัดสินอะไร และ IntersectionObserver
ก็ไม่ได้ตัดสินเช่นกัน ออบเจ็กต์ options
ใช้ตัวเลือก root
ซึ่งช่วยให้คุณกำหนดทางเลือกอื่นนอกเหนือจากวิวพอร์ตเป็นรูทได้ โปรดทราบว่า root
ต้องเป็นระดับบนขององค์ประกอบที่พบทั้งหมด
ตัดกันทั้งหมด
ไม่เอาด้วยหรอก นักพัฒนาแอปแย่ การทำเช่นนี้ไม่ได้คำนึงถึงการใช้งานรอบ CPU ของผู้ใช้ ลองมาดูตัวอย่างตัวเลื่อนแบบอินฟินิตี้กัน ในกรณีนี้ เราขอแนะนำให้เพิ่ม Sentinel ลงใน DOM และสังเกต (และรีไซเคิล) รายการเหล่านั้น คุณควรเพิ่มรายการตรวจสอบใกล้กับรายการสุดท้ายในแถบเลื่อนแบบไม่สิ้นสุด เมื่อรายการดังกล่าวปรากฏขึ้น คุณสามารถใช้การเรียกกลับเพื่อโหลดข้อมูล สร้างรายการถัดไป แนบรายการเหล่านั้นกับ DOM และจัดตำแหน่งรายการดังกล่าวใหม่ตามความเหมาะสม หากรีไซเคิล Sentinel อย่างถูกต้อง คุณไม่จำเป็นต้องโทรหา observe()
เพิ่มเติม IntersectionObserver
ทำงานอยู่เรื่อยๆ
โปรดอัปเดตเพิ่มเติม
ดังที่ได้กล่าวไว้ก่อนหน้านี้ แคล็กแบ็กจะทริกเกอร์เพียงครั้งเดียวเมื่อองค์ประกอบที่สังเกตเห็นปรากฏขึ้นบางส่วนในมุมมอง และอีกครั้งเมื่อองค์ประกอบออกจากวิวพอร์ต วิธีนี้ช่วยให้ IntersectionObserver
ตอบคําถามที่ว่า "องค์ประกอบ X อยู่ในมุมมองไหม" อย่างไรก็ตาม ในบางกรณี การดำเนินการดังกล่าวอาจไม่เพียงพอ
ตัวเลือก 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>
จะทริกเกอร์การเรียกกลับในเวลาที่เหมาะสม อย่างไรก็ตาม ในกรณีหลัง ระบบจะตั้งค่า rootBounds
เป็น null
เพื่อหลีกเลี่ยงการรั่วไหลของข้อมูลในแหล่งที่มาต่างๆ
IntersectionObserver
Not เกี่ยวกับอะไร
สิ่งที่ควรทราบคือ IntersectionObserver
ไม่ได้ออกแบบมาให้แสดงผลแบบพิกเซลสมบูรณ์หรือเวลาในการตอบสนองต่ำ การใช้งาน Google Analytics เพื่อใช้ฟีเจอร์อย่างภาพเคลื่อนไหวที่เป็นแบบเลื่อนได้เป็นหลักมีโอกาสล้มเหลว เนื่องจากข้อมูลจะไม่อัปเดต (บอกมาตรงๆ) เมื่อถึงเวลาที่คุณจะใช้งาน คําอธิบายมีรายละเอียดเพิ่มเติมเกี่ยวกับกรณีการใช้งานเดิมสําหรับ IntersectionObserver
ฉันจะดำเนินการได้มากน้อยเพียงใดในการติดต่อกลับ
สรุปสั้นๆ: การใช้เวลาในการเรียกกลับนานเกินไปจะทำให้แอปของคุณล้าช้า โปรดใช้แนวทางปฏิบัติทั่วไปทั้งหมด
ออกไปผสานองค์ประกอบ
IntersectionObserver
ใช้งานได้กับเบราว์เซอร์หลายรุ่นเนื่องจากมีให้บริการในเบราว์เซอร์ที่ทันสมัยทั้งหมด หากจำเป็น คุณสามารถใช้ polyfill ในเบราว์เซอร์รุ่นเก่าได้ ซึ่งอยู่ในที่เก็บข้อมูลของ WICG แน่นอนว่าคุณจะไม่ได้รับประโยชน์ด้านประสิทธิภาพจากการใช้โพลีฟีลนั้น ซึ่งการติดตั้งใช้งานแบบเนทีฟจะให้คุณได้
คุณสามารถเริ่มใช้ IntersectionObserver
ได้ทันที โปรดบอกเราว่าคุณคิดอะไรได้บ้าง