การสร้างส่วนหัวแบบไดนามิกด้วยผู้สังเกตการณ์ทางแยก
เผยแพร่แล้ว: 2022-03-10Intersection Observer API เป็น JavaScript API ที่ช่วยให้เราสามารถสังเกตองค์ประกอบและตรวจจับเมื่อผ่านจุดที่ระบุในคอนเทนเนอร์แบบเลื่อน ซึ่งมักจะ (แต่ไม่เสมอไป) วิวพอร์ต ซึ่งจะทริกเกอร์ฟังก์ชันเรียกกลับ
ผู้สังเกตการณ์ทางแยกนั้นมีประสิทธิภาพมากกว่าการฟังเหตุการณ์การเลื่อนบนเธรดหลัก เนื่องจากเป็นแบบอะซิงโครนัส และการเรียกกลับจะทำงานก็ต่อเมื่อองค์ประกอบที่เรากำลังสังเกตอยู่ตรงตามเกณฑ์ที่ระบุ ทุกครั้งที่อัปเดตตำแหน่งการเลื่อน ในบทความนี้ เราจะอธิบายตัวอย่างวิธีการใช้ Intersection Observer เพื่อสร้างส่วนประกอบส่วนหัวคงที่ซึ่งจะเปลี่ยนแปลงเมื่อตัดกับส่วนต่างๆ ของหน้าเว็บ
การใช้งานพื้นฐาน
ในการใช้ Intersection Observer เราต้องสร้าง Observer ขึ้นมาก่อน ซึ่งต้องใช้พารามิเตอร์สองตัว: วัตถุที่มีตัวเลือกของผู้สังเกตการณ์ และฟังก์ชันเรียกกลับที่เราต้องการดำเนินการเมื่อใดก็ตามที่องค์ประกอบที่เรากำลังสังเกต (เรียกว่าเป้าหมายผู้สังเกตการณ์) ตัดกัน ด้วยรูท (คอนเทนเนอร์แบบเลื่อนซึ่งต้องเป็นบรรพบุรุษขององค์ประกอบเป้าหมาย)
const options = { root: document.querySelector('[data-scroll-root]'), rootMargin: '0px', threshold: 1.0 } const callback = (entries, observer) => { entries.forEach((entry) => console.log(entry)) } const observer = new IntersectionObserver(callback, options)
เมื่อเราสร้างผู้สังเกตการณ์แล้ว เราต้องสั่งให้ผู้สังเกตการณ์ดูองค์ประกอบเป้าหมาย:
const targetEl = document.querySelector('[data-target]') observer.observe(targetEl)
ค่าตัวเลือกใดๆ สามารถละเว้นได้ เนื่องจากค่าเหล่านั้นจะถอยกลับไปเป็นค่าเริ่มต้น:
const options = { rootMargin: '0px', threshold: 1.0 }
หากไม่มีการระบุรูท ระบบจะจัดประเภทเป็นวิวพอร์ตของเบราว์เซอร์ ตัวอย่างโค้ดด้านบนแสดงค่าเริ่มต้นสำหรับทั้ง rootMargin
และ threshold
สิ่งเหล่านี้อาจมองเห็นได้ยาก ดังนั้นจึงควรอธิบาย:
rootMargin
ค่า rootMargin
นั้นเหมือนกับการเพิ่มระยะขอบ CSS ให้กับองค์ประกอบรูท และเช่นเดียวกับระยะขอบ สามารถรับค่าได้หลายค่า รวมถึงค่าลบด้วย องค์ประกอบเป้าหมายจะถือว่าตัดกันเมื่อเทียบกับระยะขอบ
นั่นหมายความว่าองค์ประกอบในทางเทคนิคสามารถจัดประเภทเป็น "ตัดกัน" ได้แม้ว่าจะไม่อยู่ในมุมมองก็ตาม (หากรูทการเลื่อนของเราคือวิวพอร์ต)
rootMargin
ค่าเริ่มต้นเป็น 0px
แต่สามารถรับสตริงที่ประกอบด้วยหลายค่าได้ เช่นเดียวกับการใช้คุณสมบัติ margin
ใน CSS
threshold
threshold
สามารถประกอบด้วยค่าเดียวหรืออาร์เรย์ของค่าระหว่าง 0 ถึง 1 ซึ่งแสดงถึง สัดส่วนขององค์ประกอบที่ต้องอยู่ภายในขอบเขตของรากเพื่อให้ถือว่าตัดกัน การใช้ค่าเริ่มต้นเป็น 1 การเรียกกลับจะเริ่มทำงานเมื่อ 100% ขององค์ประกอบเป้าหมายมองเห็นได้ภายในรูท
ไม่ใช่เรื่องง่ายที่จะเห็นภาพเมื่อองค์ประกอบจะถูกจัดประเภทเป็นมองเห็นได้โดยใช้ตัวเลือกเหล่านี้ ฉันได้สร้างเครื่องมือเล็กๆ เพื่อช่วยในการจับกับ Intersection Observer
การสร้างส่วนหัว
เมื่อเข้าใจหลักการพื้นฐานแล้ว มาเริ่มสร้างส่วนหัวแบบไดนามิกกันเถอะ เราจะเริ่มต้นด้วยหน้าเว็บที่แบ่งออกเป็นส่วนต่างๆ ภาพนี้แสดงเลย์เอาต์ที่สมบูรณ์ของเพจที่เราจะสร้าง:
ฉันได้รวมการสาธิตไว้ที่ส่วนท้ายของบทความนี้ ดังนั้นอย่าลังเลที่จะข้ามไปที่มันโดยตรงหากคุณต้องการยกเลิกการเลือกโค้ด (นอกจากนี้ยังมีที่เก็บ Github)
แต่ละส่วนมีความสูงขั้นต่ำ 100vh
(แม้ว่าจะยาวกว่านี้ก็ได้ ขึ้นอยู่กับเนื้อหา) ส่วนหัวของเราได้รับการแก้ไขที่ด้านบนของหน้าและยังคงอยู่ในขณะที่ผู้ใช้เลื่อน (โดยใช้ position: fixed
) ส่วนต่าง ๆ มีพื้นหลังสีต่างกัน และเมื่อตรงกับส่วนหัว สีของส่วนหัวจะเปลี่ยนเพื่อเสริมสีของส่วนนั้น นอกจากนี้ยังมีเครื่องหมายเพื่อแสดงส่วนปัจจุบันที่ผู้ใช้อยู่ ซึ่งจะเลื่อนไปมาเมื่อส่วนถัดไปมาถึง เพื่อให้เราตรงไปยังโค้ดที่เกี่ยวข้องได้ง่ายขึ้น ฉันได้ตั้งค่าการสาธิตขั้นต่ำด้วยจุดเริ่มต้นของเรา (ก่อนที่เราจะเริ่มใช้ Intersection Observer API) ในกรณีที่คุณต้องการปฏิบัติตาม
มาร์กอัป
เราจะเริ่มต้นด้วย HTML สำหรับส่วนหัวของเรา นี่จะเป็นส่วนหัวที่ค่อนข้างง่ายพร้อมโฮมลิงค์และการนำทาง ไม่มีอะไรพิเศษเป็นพิเศษ แต่เราจะใช้แอตทริบิวต์ข้อมูลสองสามอย่าง: data-header
สำหรับส่วนหัวเอง (เพื่อให้เราสามารถกำหนดเป้าหมายองค์ประกอบด้วย JS) และลิงก์สมอสามลิงก์ที่มีแอตทริบิวต์ data-link
ซึ่งจะเลื่อนผู้ใช้ไปยังส่วนที่เกี่ยวข้องเมื่อคลิก:
<header data-header> <nav class="header__nav"> <div class="header__left-content"> <a href="#0">Home</a> </div> <ul class="header__list"> <li> <a href="#about-us" data-link>About us</a> </li> <li> <a href="#flavours" data-link>The flavours</a> </li> <li> <a href="#get-in-touch" data-link>Get in touch</a> </li> </ul> </nav> </header>
ถัดไป HTML สำหรับส่วนที่เหลือของหน้าเว็บของเรา ซึ่งแบ่งออกเป็นส่วนต่างๆ เพื่อความกระชับ ฉันได้รวมเฉพาะส่วนที่เกี่ยวข้องกับบทความ แต่มาร์กอัปแบบเต็มรวมอยู่ในการสาธิต แต่ละส่วนมีแอตทริบิวต์ข้อมูลที่ระบุชื่อสีพื้นหลัง และ id
ที่สอดคล้องกับลิงก์สมอตัวใดตัวหนึ่งในส่วนหัว:
<main> <section data-section="raspberry"> <!--Section content--> </section> <section data-section="mint"> <!--Section content--> </section> <section data-section="vanilla"> <!--Section content--> </section> <section data-section="chocolate"> <!--Section content--> </section> </main>
เราจะวางตำแหน่งส่วนหัวของเราด้วย CSS เพื่อให้คงที่ที่ด้านบนของหน้าเมื่อผู้ใช้เลื่อน:
header { position: fixed; width: 100%; }
เราจะกำหนดความสูงขั้นต่ำของส่วนต่างๆ และจัดกึ่งกลางเนื้อหาด้วย (โค้ดนี้ไม่จำเป็นสำหรับ Intersection Observer ในการทำงาน แต่มีไว้สำหรับการออกแบบเท่านั้น)
section { padding: 5rem 0; min-height: 100vh; display: flex; justify-content: center; align-items: center; }
คำเตือน iframe
ขณะสร้างตัวอย่าง Codepen นี้ ฉันพบปัญหาที่น่าสับสนซึ่งโค้ด Intersection Observer ของฉันที่ น่าจะ ทำงานได้อย่างสมบูรณ์ล้มเหลวในการเรียกกลับที่จุดที่ถูกต้องของทางแยก แต่แทนที่จะยิงเมื่อองค์ประกอบเป้าหมายตัดกับขอบวิวพอร์ต หลังจากเกาหัวเล็กน้อย ฉันก็รู้ว่านี่เป็นเพราะใน Codepen เนื้อหาถูกโหลดภายใน iframe ซึ่งได้รับการปฏิบัติแตกต่างออกไป (ดูส่วนเอกสาร MDN เกี่ยวกับการตัดและสี่เหลี่ยมทางแยกสำหรับรายละเอียดทั้งหมด)
ในการแก้ปัญหาชั่วคราว ในการสาธิต เราสามารถรวมมาร์กอัปของเราไว้ในองค์ประกอบอื่น ซึ่งจะทำหน้าที่เป็นคอนเทนเนอร์การเลื่อน — รูทในตัวเลือก IO ของเรา — แทนที่จะเป็นวิวพอร์ตของเบราว์เซอร์ อย่างที่เราคาดไว้:
<div class="scroller" data-scroller> <header data-header> <!--Header content--> </header> <main> <!--Sections--> </main> </div>
หากคุณต้องการดูวิธีใช้วิวพอร์ตเป็นรูทแทนการสาธิตเดียวกัน สิ่งนี้จะรวมอยู่ในที่เก็บ Github
CSS
ใน CSS ของเรา เราจะกำหนดคุณสมบัติที่กำหนดเองบางอย่างสำหรับสีที่เราใช้ นอกจากนี้ เราจะกำหนดคุณสมบัติที่กำหนดเองเพิ่มเติมสองรายการสำหรับข้อความส่วนหัวและสีพื้นหลัง และตั้งค่าเริ่มต้นบางส่วน (เราจะอัปเดตคุณสมบัติที่กำหนดเองทั้งสองนี้สำหรับส่วนต่างๆ ในภายหลัง)
:root { --mint: #5ae8d5; --chocolate: #573e31; --raspberry: #f2308e; --vanilla: #faf2c8; --headerText: var(--vanilla); --headerBg: var(--raspberry); }
เราจะใช้คุณสมบัติที่กำหนดเองเหล่านี้ในส่วนหัวของเรา:
header { background-color: var(--headerBg); color: var(--headerText); }
เราจะกำหนดสีสำหรับส่วนต่างๆ ของเราด้วย ฉันกำลังใช้แอตทริบิวต์ data เป็นตัวเลือก แต่คุณสามารถใช้คลาสได้อย่างง่ายดายหากต้องการ
[data-section="raspberry"] { background-color: var(--raspberry); color: var(--vanilla); } [data-section="mint"] { background-color: var(--mint); color: var(--chocolate); } [data-section="vanilla"] { background-color: var(--vanilla); color: var(--chocolate); } [data-section="chocolate"] { background-color: var(--chocolate); color: var(--vanilla); }
นอกจากนี้เรายังสามารถกำหนดรูปแบบบางอย่างสำหรับส่วนหัวของเราเมื่อแต่ละส่วนอยู่ในมุมมอง:
/* Header */ [data-theme="raspberry"] { --headerText: var(--raspberry); --headerBg: var(--vanilla); } [data-theme="mint"] { --headerText: var(--mint); --headerBg: var(--chocolate); } [data-theme="chocolate"] { --headerText: var(--chocolate); --headerBg: var(--vanilla); }
มีกรณีที่ชัดเจนกว่าสำหรับการใช้แอตทริบิวต์ data ที่นี่ เนื่องจากเราจะสลับแอตทริบิวต์ data-theme
ของส่วนหัวในแต่ละทางแยก
การสร้างผู้สังเกตการณ์
ตอนนี้เรามี HTML และ CSS พื้นฐานสำหรับการตั้งค่าหน้าเว็บแล้ว เราจึงสามารถสร้างผู้สังเกตการณ์เพื่อดูส่วนต่างๆ ของเราที่ปรากฏในมุมมองได้ เราต้องการเริ่มการติดต่อกลับเมื่อใดก็ตามที่ส่วนติดต่อกับด้านล่างของส่วนหัวขณะที่เราเลื่อนลงมาในหน้า ซึ่งหมายความว่าเราจำเป็นต้องตั้งค่าระยะขอบรากติดลบที่สอดคล้องกับความสูงของส่วนหัว
const header = document.querySelector('[data-header]') const sections = [...document.querySelectorAll('[data-section]')] const scrollRoot = document.querySelector('[data-scroller]') const options = { root: scrollRoot, rootMargin: `${header.offsetHeight * -1}px`, threshold: 0 }
เรากำลังตั้งค่าขีดจำกัด 0 เนื่องจากเราต้องการให้เริ่มทำงานหากส่วน ใด ส่วนหนึ่งของส่วนตัดกับระยะขอบราก
ก่อนอื่น เราจะสร้างการเรียกกลับเพื่อเปลี่ยนค่า data-theme
ของส่วนหัว (สิ่งนี้ตรงไปตรงมามากกว่าการเพิ่มและลบคลาส โดยเฉพาะอย่างยิ่งเมื่อองค์ประกอบส่วนหัวของเราอาจมีการใช้คลาสอื่น)
/* The callback that will fire on intersection */ const onIntersect = (entries) => { entries.forEach((entry) => { const theme = entry.target.dataset.section header.setAttribute('data-theme', theme) }) }
จากนั้นเราจะสร้างผู้สังเกตการณ์เพื่อดูส่วนที่ตัดกัน:
/* Create the observer */ const observer = new IntersectionObserver(onIntersect, options) /* Set our observer to observe each section */ sections.forEach((section) => { observer.observe(section) })
ตอนนี้เราควรจะเห็นสีส่วนหัวของเราอัปเดตเมื่อแต่ละส่วนตรงกับส่วนหัว
อย่างไรก็ตาม คุณอาจสังเกตเห็นว่าสีไม่ได้รับการอัปเดตอย่างถูกต้องเมื่อเราเลื่อนลง อันที่จริง ส่วนหัวกำลังอัปเดตด้วยสีของส่วนก่อนหน้าทุกครั้ง! ในทางกลับกัน มันทำงานได้อย่างสมบูรณ์ เราจำเป็นต้องกำหนดทิศทางการเลื่อนและเปลี่ยนพฤติกรรมตามนั้น
ค้นหาทิศทางการเลื่อน
เราจะตั้งค่าตัวแปรใน JS ของเราสำหรับทิศทางของการเลื่อนด้วยค่าเริ่มต้น 'up'
และอีกค่าหนึ่งสำหรับตำแหน่งการเลื่อนที่ทราบล่าสุด ( prevYPosition
) จากนั้น ภายในการเรียกกลับ หากตำแหน่งเลื่อนมากกว่าค่าก่อนหน้า เราสามารถตั้งค่า direction
เป็น 'down'
หรือ 'up'
หากกลับกัน
let direction = 'up' let prevYPosition = 0 const setScrollDirection = () => { if (scrollRoot.scrollTop > prevYPosition) { direction = 'down' } else { direction = 'up' } prevYPosition = scrollRoot.scrollTop } const onIntersect = (entries, observer) => { entries.forEach((entry) => { setScrollDirection() /* ... */ }) }
นอกจากนี้ เราจะสร้างฟังก์ชันใหม่เพื่ออัปเดตสีของส่วนหัว โดยส่งผ่านไปยังส่วนเป้าหมายเป็นอาร์กิวเมนต์:
const updateColors = (target) => { const theme = target.dataset.section header.setAttribute('data-theme', theme) } const onIntersect = (entries) => { entries.forEach((entry) => { setScrollDirection() updateColors(entry.target) }) }
จนถึงตอนนี้ เราไม่ควรเห็นการเปลี่ยนแปลงพฤติกรรมของส่วนหัวของเรา แต่ตอนนี้เรารู้ทิศทางการเลื่อนแล้ว เราก็สามารถส่งผ่านไปยังเป้าหมายอื่นสำหรับ updateColors()
ของเราได้ หากทิศทางการเลื่อนขึ้น เราจะใช้เป้าหมายรายการ ถ้ามันลง เราจะใช้ส่วนถัดไป (ถ้ามี)
const getTargetSection = (target) => { if (direction === 'up') return target if (target.nextElementSibling) { return target.nextElementSibling } else { return target } } const onIntersect = (entries) => { entries.forEach((entry) => { setScrollDirection() const target = getTargetSection(entry.target) updateColors(target) }) }
อย่างไรก็ตาม ยังมีปัญหาอีกประการหนึ่ง: ส่วนหัวจะอัปเดตไม่เฉพาะเมื่อส่วนนั้นกระทบกับส่วนหัว แต่เมื่อองค์ประกอบถัดไปปรากฏให้เห็นที่ด้านล่างของวิวพอร์ต นี่เป็นเพราะว่าผู้สังเกตการณ์ของเราทำการเรียกกลับสองครั้ง: หนึ่งครั้งเมื่อองค์ประกอบเข้ามา และอีกครั้งเมื่อออกจากองค์ประกอบ
เพื่อตรวจสอบว่าส่วนหัวควรอัปเดตหรือไม่ เราสามารถใช้คีย์ isIntersecting
จากออบเจ็กต์ entry
มาสร้างฟังก์ชันอื่นเพื่อคืนค่าบูลีนว่าสีส่วนหัวควรอัปเดตหรือไม่:
const shouldUpdate = (entry) => { if (direction === 'down' && !entry.isIntersecting) { return true } if (direction === 'up' && entry.isIntersecting) { return true } return false }
เราจะอัปเดต onIntersect()
ของเราตามลำดับ:
const onIntersect = (entries) => { entries.forEach((entry) => { setScrollDirection() /* Do nothing if no need to update */ if (!shouldUpdate(entry)) return const target = getTargetSection(entry.target) updateColors(target) }) }
ตอนนี้สีของเราควรอัปเดตอย่างถูกต้อง เราสามารถตั้งค่าการเปลี่ยน CSS เพื่อให้เอฟเฟกต์ดีขึ้นเล็กน้อย:
header { transition: background-color 200ms, color 200ms; }
การเพิ่มไดนามิกมาร์กเกอร์
ต่อไป เราจะเพิ่มเครื่องหมายที่ส่วนหัวซึ่งจะอัปเดตตำแหน่งเมื่อเราเลื่อนไปยังส่วนต่างๆ เราสามารถใช้องค์ประกอบเทียมสำหรับสิ่งนี้ ดังนั้นเราจึงไม่จำเป็นต้องเพิ่มอะไรใน HTML ของเรา เราจะใส่สไตล์ CSS ง่ายๆ เพื่อจัดตำแหน่งไว้ที่ด้านบนซ้ายของส่วนหัว และกำหนดสีพื้นหลัง เราใช้ currentColor
สำหรับสิ่งนี้ เนื่องจากจะใช้ค่าของสีข้อความส่วนหัว:
header::after { content: ''; position: absolute; top: 0; left: 0; height: 0.4rem; background-color: currentColor; }
เราสามารถใช้คุณสมบัติที่กำหนดเองสำหรับความกว้าง โดยมีค่าเริ่มต้นเป็น 0 เราจะใช้คุณสมบัติที่กำหนดเองสำหรับค่าการแปล x เราจะตั้งค่าสำหรับสิ่งเหล่านี้ในฟังก์ชันเรียกกลับของเราเมื่อผู้ใช้เลื่อน
header::after { content: ''; position: absolute; top: 0; left: 0; height: 0.4rem; width: var(--markerWidth, 0); background-color: currentColor; transform: translate3d(var(--markerLeft, 0), 0, 0); }
ตอนนี้ เราสามารถเขียนฟังก์ชันที่จะอัปเดตความกว้างและตำแหน่งของเครื่องหมายที่จุดตัด:
const updateMarker = (target) => { const id = target.id /* Do nothing if no target ID */ if (!id) return /* Find the corresponding nav link, or use the first one */ let link = headerLinks.find((el) => { return el.getAttribute('href') === `#${id}` }) link = link || headerLinks[0] /* Get the values and set the custom properties */ const distanceFromLeft = link.getBoundingClientRect().left header.style.setProperty('--markerWidth', `${link.clientWidth}px`) header.style.setProperty('--markerLeft', `${distanceFromLeft}px`) }
เราสามารถเรียกใช้ฟังก์ชันได้พร้อมๆ กับอัปเดตสี:
const onIntersect = (entries) => { entries.forEach((entry) => { setScrollDirection() if (!shouldUpdate(entry)) return const target = getTargetSection(entry.target) updateColors(target) updateMarker(target) }) }
นอกจากนี้เรายังต้องกำหนดตำแหน่งเริ่มต้นสำหรับเครื่องหมาย เพื่อไม่ให้ปรากฏโดยไม่ทราบสาเหตุ เมื่อโหลดเอกสาร เราจะเรียก updateMarker()
โดยใช้ส่วนแรกเป็นเป้าหมาย:
document.addEventListener('readystatechange', e => { if (e.target.readyState === 'complete') { updateMarker(sections[0]) } })
สุดท้าย ให้เพิ่มการเปลี่ยน CSS เพื่อให้เครื่องหมายเลื่อนข้ามส่วนหัวจากลิงก์หนึ่งไปยังลิงก์ถัดไป ในขณะที่เรากำลังเปลี่ยนคุณสมบัติ width
เราสามารถใช้ will-change
เพื่อให้เบราว์เซอร์ทำการเพิ่มประสิทธิภาพได้
header::after { transition: transform 250ms, width 200ms, background-color 200ms; will-change: width; }
เลื่อนเรียบ
เพื่อสัมผัสสุดท้าย คงจะดีถ้าเมื่อผู้ใช้คลิกลิงก์ พวกเขาเลื่อนหน้าลงมาอย่างราบรื่น แทนที่จะข้ามไปยังส่วนนั้น ทุกวันนี้ เราสามารถทำได้ใน CSS ของเรา โดยไม่ต้องใช้ JS! เพื่อประสบการณ์ที่เข้าถึงได้มากขึ้น เป็นการดีที่จะเคารพการตั้งค่าการเคลื่อนไหวของผู้ใช้โดยใช้การเลื่อนอย่างราบรื่นเท่านั้น หากพวกเขาไม่ได้ระบุการตั้งค่าสำหรับการเคลื่อนไหวที่ลดลงในการตั้งค่าระบบของพวกเขา:
@media (prefers-reduced-motion: no-preference) { .scroller { scroll-behavior: smooth; } }
สาธิตขั้นสุดท้าย
การนำขั้นตอนข้างต้นทั้งหมดมารวมกันส่งผลให้เกิดการสาธิตที่สมบูรณ์
รองรับเบราว์เซอร์
Intersection Observer ได้รับการสนับสนุนอย่างกว้างขวางในเบราว์เซอร์สมัยใหม่ ในกรณีที่จำเป็น ก็สามารถ polyfilled สำหรับเบราว์เซอร์รุ่นเก่า — แต่ฉันชอบใช้วิธีการเพิ่มประสิทธิภาพแบบก้าวหน้าถ้าเป็นไปได้ ในกรณีของส่วนหัวของเรา จะไม่ส่งผลเสียอย่างใหญ่หลวงต่อประสบการณ์ของผู้ใช้ในการจัดเตรียมเวอร์ชันที่เรียบง่ายและไม่เปลี่ยนแปลงสำหรับเบราว์เซอร์ที่ไม่สนับสนุน
ในการตรวจสอบว่ารองรับ Intersection Observer หรือไม่ เราสามารถใช้สิ่งต่อไปนี้:
if ('IntersectionObserver' in window && 'IntersectionObserverEntry' in window && 'intersectionRatio' in window.IntersectionObserverEntry.prototype) { /* Code to execute if IO is supported */ } else { /* Code to execute if not supported */ }
ทรัพยากร
อ่านเพิ่มเติมเกี่ยวกับผู้สังเกตการณ์ทางแยก:
- เอกสารประกอบที่กว้างขวาง พร้อมตัวอย่างการใช้งานจริงจาก MDN
- เครื่องมือสร้างภาพทางแยกผู้สังเกตการณ์
- การมองเห็นองค์ประกอบกำหนดเวลาด้วย Intersection Observer API - บทช่วยสอนอื่นจาก MDN ที่พิจารณาว่าสามารถใช้ IO เพื่อติดตามการมองเห็นโฆษณาได้อย่างไร
- บทความนี้โดย Denys Mishunov ครอบคลุมการใช้งานอื่นๆ สำหรับ IO รวมถึงเนื้อหาที่โหลดแบบ Lazy Loading แม้ว่าตอนนี้จะไม่จำเป็นแล้ว (ต้องขอบคุณแอตทริบิวต์การ
loading
) แต่ก็ยังมีอะไรให้เรียนรู้อีกมากที่นี่