เพียงลบฟังก์ชันการหมดเวลาและสลัดข้อบกพร่องออกไป นี่คือเหตุการณ์ที่คุณต้องการจริงๆ คือ Scrollend
ก่อนเหตุการณ์ scrollend
ไม่มีวิธีที่เชื่อถือได้ในการตรวจสอบว่าการเลื่อนเสร็จสมบูรณ์แล้ว ซึ่งหมายความว่าเหตุการณ์จะเริ่มทำงานล่าช้าหรือขณะที่นิ้วของผู้ใช้ยังวางอยู่ที่หน้าจอ ความไม่แน่นอนนี้เมื่อทราบว่าการเลื่อนจบลงจริงๆ แล้ว ทำให้เกิดข้อบกพร่องและทำให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ไม่ดี
document.onscroll = event => { clearTimeout(window.scrollEndTimer) window.scrollEndTimer = setTimeout(callback, 100) }
วิธีที่ดีที่สุดที่กลยุทธ์ setTimeout()
นี้ทำได้คือรู้ว่าการเลื่อนหยุดลงเป็นเวลา 100ms
แล้วหรือไม่ ซึ่งทำให้ดูเหมือนการเลื่อนมีเหตุการณ์หยุดชั่วคราว ไม่ใช่การเลื่อนได้สิ้นสุดเหตุการณ์
หลังเหตุการณ์ scrollend
เบราว์เซอร์จะทำการประเมินที่ยากๆ นี้ให้คุณ
document.onscrollend = event => {…}
นั่นเป็นสิ่งที่ดี มีเวลาที่เหมาะสมและเต็มไปด้วยสภาวะที่มีความหมาย ก่อนที่จะปล่อยออกมา
ลองใช้งาน
รายละเอียดเหตุการณ์
เหตุการณ์ scrollend
จะเริ่มทำงานในกรณีต่อไปนี้
- เบราว์เซอร์ไม่เคลื่อนไหวหรือแปลการเลื่อนอีกต่อไป
- ปล่อยการสัมผัสของผู้ใช้แล้ว
- ตัวชี้ของผู้ใช้ปล่อยนิ้วโป้งเลื่อน
- ปล่อยการกดแป้นของผู้ใช้แล้ว
- เลื่อนไปยังส่วนย่อยเสร็จสมบูรณ์แล้ว
- การสแนปการเลื่อนเสร็จสมบูรณ์แล้ว
- scrollTo()
เสร็จสมบูรณ์แล้ว
- ผู้ใช้เลื่อนวิวพอร์ตภาพ
เหตุการณ์ scrollend
ไม่เริ่มทำงานในกรณีต่อไปนี้
- ท่าทางสัมผัสของผู้ใช้ไม่ส่งผลให้เกิดการเปลี่ยนแปลงตำแหน่งการเลื่อนใดๆ (ไม่มีการแปล)
- scrollTo()
ไม่พบคำแปลใดๆ
เหตุผลที่ทำให้เหตุการณ์นี้ใช้เวลามากมายในการเข้ามาในแพลตฟอร์มบนเว็บก็เนื่องมาจากมีรายละเอียดเล็กๆ น้อยๆ จำนวนมากที่ต้องมีรายละเอียดข้อกำหนด หนึ่งในพื้นที่ที่ซับซ้อนที่สุดคือการแสดงรายละเอียด scrollend
สำหรับวิวพอร์ตภาพเทียบกับเอกสาร ลองนึกถึงหน้าเว็บที่คุณซูมเข้า คุณสามารถเลื่อนดูได้เมื่ออยู่ในสถานะซูม และไม่จำเป็นต้องเลื่อนเอกสาร ขอให้มั่นใจว่าแม้การโต้ตอบการเลื่อนของผู้ใช้สำหรับวิวพอร์ตภาพนี้ก็จะปล่อยเหตุการณ์ scrollend
เมื่อเสร็จสิ้น
การใช้กิจกรรม
คุณลงทะเบียน Listener ได้ 2 วิธีเช่นเดียวกับเหตุการณ์การเลื่อนอื่นๆ
addEventListener("scrollend", (event) => {
// scroll ended
});
aScrollingElement.addEventListener("scrollend", (event) => {
// scroll ended
});
หรือใช้พร็อพเพอร์ตี้เหตุการณ์
document.onscrollend = (event) => {
// scroll ended
};
aScrollingElement.onscrollend = (event) => {
// scroll ended
};
โพลีฟิลล์และการเพิ่มประสิทธิภาพแบบต่อเนื่อง
หากคุณต้องการใช้กิจกรรมใหม่นี้ในตอนนี้ นี่คือคำแนะนำที่ดีที่สุดของเรา คุณยังคงใช้กลยุทธ์การสิ้นสุดการเลื่อนปัจจุบันต่อไปได้ (หากมี) และในตอนเริ่มต้น ให้ตรวจสอบการรองรับรายการต่อไปนี้
'onscrollend' in window
// true, if available
ซึ่งจะรายงานว่าเป็นจริงหรือเท็จ ขึ้นอยู่กับว่าเบราว์เซอร์เสนอเหตุการณ์ดังกล่าวหรือไม่ ด้วยการตรวจสอบนี้ คุณสามารถทำให้รหัสแตกแขนงได้:
if ('onscrollend' in window) {
document.onscrollend = callback
}
else {
document.onscroll = event => {
clearTimeout(window.scrollEndTimer)
window.scrollEndTimer = setTimeout(callback, 100)
}
}
นี่คือการเริ่มต้นที่ดีในการปรับปรุงกิจกรรม scrollend
อย่างต่อเนื่องเมื่อพร้อมใช้งาน คุณอาจลองใช้ polyfill (NPM) ที่ผมสร้างขึ้นมาเพื่อให้ทำงานได้ดีที่สุด ดังนี้
import {scrollend} from "scrollyfills"
// then use scrollend as if it's existed this whole time
document.onscrollend = callback
Polyfill จะเพิ่มประสิทธิภาพการใช้เหตุการณ์ scrollend
ในตัวของเบราว์เซอร์ (หากมี) หากไม่มี สคริปต์จะดูเหตุการณ์ตัวชี้และเลื่อนเพื่อประเมินเหตุการณ์สิ้นสุดอย่างดีที่สุดเท่าที่ทำได้
Use Case
คุณควรหลีกเลี่ยงการคำนวณภาระงานหนักๆ ขณะเลื่อนดูเนื้อหา วิธีนี้ช่วยให้มั่นใจว่าการเลื่อนจะใช้หน่วยความจำและการประมวลผลได้มากเท่าที่ทำได้เพื่อการใช้งานที่ราบรื่น การใช้เหตุการณ์ scrollend
เป็นโอกาสที่เหมาะอย่างยิ่งในการเรียกและพยายามทำเรื่องยากๆ เนื่องจากการเลื่อนไม่ได้เกิดขึ้นแล้ว
คุณใช้เหตุการณ์ scrollend
เพื่อทริกเกอร์การดำเนินการต่างๆ ได้ กรณีการใช้งานที่พบบ่อยคือการซิงค์องค์ประกอบ UI ที่เกี่ยวข้องเข้ากับตำแหน่งที่การเลื่อนหยุดลง ตัวอย่างเช่น
- การซิงค์ตำแหน่งการเลื่อนภาพหมุนที่มีเครื่องหมายจุด
- การซิงค์รายการในแกลเลอรีกับข้อมูลเมตา
- การดึงข้อมูลหลังจากที่ผู้ใช้เลื่อนไปยังแท็บใหม่
ลองนึกภาพสถานการณ์ เช่น ผู้ใช้ปัดอีเมลออกไป หลังจากที่ปัดเสร็จแล้ว คุณจะดำเนินการตามตำแหน่งที่ผู้ใช้เลื่อนไปได้
นอกจากนี้คุณยังใช้เหตุการณ์นี้เพื่อซิงค์ข้อมูลหลังการเลื่อนแบบเป็นโปรแกรมหรือการเลื่อนของผู้ใช้ หรือการดำเนินการต่างๆ ได้ เช่น ข้อมูลวิเคราะห์การบันทึก
นี่คือตัวอย่างที่ดีที่ต้องอัปเดตองค์ประกอบหลายรายการ เช่น ลูกศร จุด และโฟกัสตามตำแหน่งการเลื่อน ดูวิธีที่ฉันสร้างภาพสไลด์นี้บน YouTube และลองการสาธิตการใช้งานจริง
ขอขอบคุณ Mehdi Kazemi สำหรับงานด้านวิศวกรรมในเรื่องนี้ และ Robert Flack สำหรับ API และคำแนะนำในการใช้งาน