Intersection Observer v2 เพิ่มความสามารถในการสังเกตไม่เพียงเฉพาะจุดตัดเท่านั้น แต่ยังตรวจจับได้ด้วยว่ามีการแสดงองค์ประกอบที่ตัดกัน ณ เวลาที่มีการตัดกันหรือไม่
Intersection Observer v1 เป็นหนึ่งใน API ที่น่าจะได้รับความนิยมอย่างแพร่หลาย และตอนนี้ที่Safari รองรับด้วย ก็ทำให้ API นี้ใช้งานได้อย่างแพร่หลายในเบราว์เซอร์หลักทุกรุ่นแล้ว หากต้องการทบทวนข้อมูลเกี่ยวกับ API อย่างรวดเร็ว เราขอแนะนําให้ดูเคล็ดลับขนาดเล็กที่มีประสิทธิภาพสูงของ Surma ใน Intersection Observer v1 ที่ฝังไว้ด้านล่าง
นอกจากนี้ คุณยังอ่านบทความเชิงลึกของ Surma ได้ด้วย
ผู้คนใช้ Intersection Observer v1 สําหรับกรณีการใช้งานที่หลากหลาย เช่น การโหลดรูปภาพและวิดีโอแบบ Lazy Loading, การแจ้งเตือนเมื่อองค์ประกอบถึง position: sticky
, การเรียกเหตุการณ์ Analytics และอื่นๆ อีกมากมาย
ดูรายละเอียดทั้งหมดได้ในเอกสาร Intersection Observer ใน MDN แต่เพื่อเป็นการช่วยเตือน หน้าตาของ Intersection Observer v1 API ในกรณีพื้นฐานที่สุดมีดังนี้
const onIntersection = (entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
console.log(entry);
}
}
};
const observer = new IntersectionObserver(onIntersection);
observer.observe(document.querySelector('#some-target'));
Intersection Observer v1 มีข้อจํากัดอะไรบ้าง
ขออธิบายให้ชัดเจน Intersection Observer v1 นั้นยอดเยี่ยม แต่ก็ไม่ได้สมบูรณ์แบบ มีบางกรณีที่ API ทำงานไม่ได้ มาดูรายละเอียดกัน
Intersection Observer v1 API สามารถบอกได้เมื่อมีการเลื่อนองค์ประกอบไปยังวิวพอร์ตของหน้าต่าง แต่จะไม่บอกคุณว่าองค์ประกอบถูกบดบังโดยเนื้อหาหน้าเว็บอื่นๆ หรือไม่ (นั่นคือเมื่อองค์ประกอบถูกบดบัง) หรือการแสดงผลภาพองค์ประกอบได้รับการแก้ไขโดยเอฟเฟกต์ภาพ เช่น transform
, opacity
, filter
หรือไม่ ซึ่งทำให้องค์ประกอบนั้นมองไม่เห็นได้อย่างมีประสิทธิภาพ
สําหรับองค์ประกอบในเอกสารระดับบนสุด ข้อมูลนี้สามารถระบุได้โดยการวิเคราะห์ DOM ผ่าน JavaScript เช่น ผ่าน DocumentOrShadowRoot.elementFromPoint()
แล้วเจาะลึกเพิ่มเติม
ในทางตรงกันข้าม คุณจะไม่สามารถรับข้อมูลเดียวกันได้หากองค์ประกอบที่เป็นปัญหาอยู่ใน iframe ของบุคคลที่สาม
เหตุใดการแสดงผลจริงจึงสำคัญมาก
ขออภัยที่อินเทอร์เน็ตเป็นพื้นที่ที่ดึงดูดผู้ไม่ประสงค์ดีที่มีเจตนาร้าย
ตัวอย่างเช่น ผู้เผยแพร่โฆษณาที่ไม่น่าไว้วางใจซึ่งแสดงโฆษณาแบบจ่ายต่อคลิกในเว็บไซต์เนื้อหาอาจมีแรงจูงใจที่จะหลอกลวงผู้ใช้ให้คลิกโฆษณาเพื่อเพิ่มการชำระคืนโฆษณาของผู้เผยแพร่โฆษณา (อย่างน้อยก็ในระยะสั้นจนกว่าเครือข่ายโฆษณาจะจับได้)
โดยปกติแล้ว โฆษณาดังกล่าวจะแสดงใน iframe
หากผู้เผยแพร่โฆษณาต้องการให้ผู้ใช้คลิกโฆษณาดังกล่าว ก็อาจทําให้ iframe ของโฆษณาโปร่งใสได้โดยใช้กฎ CSS iframe { opacity: 0; }
และวางซ้อน iframe ไว้บนสิ่งที่น่าสนใจ เช่น วิดีโอแมวน่ารักที่ผู้ใช้อยากคลิกจริงๆ
การดำเนินการนี้เรียกว่าคลิกแจ็กกิ้ง
คุณสามารถดูการโจมตีด้วยคลิกเจตนาดังกล่าวได้ในส่วนบนของการสาธิตนี้ (ลอง "ดู" วิดีโอแมวและเปิดใช้งาน "โหมดกลโกง")
คุณจะเห็นว่าโฆษณาใน iframe "คิดว่า" ได้รับการคลิกที่ถูกต้อง แม้ว่าจะโปร่งแสงโดยสมบูรณ์เมื่อคุณ (แกล้งทำเป็น) คลิกก็ตาม
Intersection Observer v2 แก้ไขปัญหานี้ได้อย่างไร
Intersection Observer v2 นำเสนอแนวคิดในการติดตาม "การแสดงผล" จริงขององค์ประกอบเป้าหมายตามที่มนุษย์จะกำหนด
การตั้งค่าตัวเลือกในตัวสร้าง จะทำให้อินสแตนซ์ที่ตัดกันของ IntersectionObserverEntry
มีช่องบูลีนใหม่ชื่อ isVisible
IntersectionObserver
ค่า true
สำหรับ isVisible
เป็นการรับประกันที่แน่ชัดจากการใช้งานพื้นฐานว่าองค์ประกอบเป้าหมายไม่ถูกบดบังโดยเนื้อหาอื่นๆ โดยสิ้นเชิง และไม่มีการใช้เอฟเฟกต์ภาพที่จะเปลี่ยนแปลงหรือบิดเบือนการแสดงผลบนหน้าจอ
ในทางตรงกันข้าม ค่า false
หมายความว่าการติดตั้งใช้งานไม่สามารถรับประกันได้
รายละเอียดที่สําคัญของข้อกําหนดคือการนําไปใช้ได้รับอนุญาตให้รายงานผลลบที่ผิดพลาด (นั่นคือ การตั้งค่า isVisible
เป็น false
แม้ว่าองค์ประกอบเป้าหมายจะมองเห็นได้ทั้งหมดและไม่มีการแก้ไข)
เบราว์เซอร์จะจำกัดการทำงานด้วยกล่องขอบเขตและเรขาคณิตแบบเส้นตรงเพื่อประสิทธิภาพหรือเหตุผลอื่นๆ โดยไม่พยายามทำให้ได้ผลลัพธ์ที่สมบูรณ์แบบแบบพิกเซลสำหรับการแก้ไข เช่น border-radius
อย่างไรก็ตาม ไม่อนุญาตให้ผลบวกลวงเกิดขึ้นไม่ว่าในกรณีใดก็ตาม (นั่นคือ การตั้งค่า isVisible
เป็น true
เมื่อองค์ประกอบเป้าหมายไม่แสดงอย่างสมบูรณ์และไม่มีการแก้ไข)
โค้ดใหม่มีลักษณะเป็นอย่างไรเมื่อใช้งานจริง
ตอนนี้ตัวสร้าง IntersectionObserver
จะรับพร็อพเพอร์ตี้การกําหนดค่าเพิ่มเติม 2 รายการ ได้แก่ delay
และ trackVisibility
delay
คือตัวเลขที่ระบุความล่าช้าขั้นต่ำเป็นมิลลิวินาทีระหว่างการแจ้งเตือนจากผู้สังเกตการณ์สําหรับเป้าหมายหนึ่งๆ
trackVisibility
คือบูลีนซึ่งระบุว่าผู้สังเกตจะติดตามการเปลี่ยนแปลงระดับการมองเห็นของเป้าหมายหรือไม่
โปรดทราบว่าเมื่อ trackVisibility
เป็น true
delay
ต้องมีค่าอย่างน้อย 100
(นั่นคือ มีการแจ้งเตือนไม่เกิน 1 ครั้งทุกๆ 100 มิลลิวินาที)
ดังที่กล่าวไว้ก่อนหน้านี้ การคำนวณการแสดงผลมีค่าใช้จ่ายสูง และข้อกําหนดนี้เป็นการป้องกันการเสื่อมประสิทธิภาพและการใช้แบตเตอรี่ นักพัฒนาแอปที่มีความรับผิดชอบจะใช้ค่าที่ยอมรับได้สูงสุดสำหรับความล่าช้า
ข้อกําหนดปัจจุบันกําหนดให้คํานวณระดับการมองเห็นดังนี้
หากแอตทริบิวต์
trackVisibility
ของผู้สังเกตการณ์คือfalse
ระบบจะถือว่าเป้าหมายนั้นมองเห็นได้ ซึ่งสอดคล้องกับลักษณะการทํางานของ v1 ปัจจุบันหากเป้าหมายมีเมทริกซ์การเปลี่ยนรูปแบบที่มีประสิทธิภาพนอกเหนือจากการเปลี่ยนรูปแบบ 2 มิติหรือการขยายขนาด 2 มิติตามสัดส่วน ระบบจะถือว่าเป้าหมายนั้นมองไม่เห็น
หากเป้าหมายหรือองค์ประกอบใดๆ ในเชนบล็อกที่ประกอบด้วยองค์ประกอบนั้นมีความทึบแสงที่มีประสิทธิภาพอื่นนอกเหนือจาก 1.0 ระบบจะถือว่าเป้าหมายนั้นมองไม่เห็น
หากเป้าหมายหรือองค์ประกอบใดๆ ในเชนบล็อกที่ประกอบด้วยมีการใช้ตัวกรอง ระบบจะถือว่าเป้าหมายนั้นมองไม่เห็น
หากการติดตั้งใช้งานไม่สามารถรับประกันได้ว่าเป้าหมายจะไม่ถูกบดบังโดยเนื้อหาอื่นๆ ของหน้าเว็บเลย ระบบจะถือว่าเป้าหมายนั้นมองไม่เห็น
ซึ่งหมายความว่าการใช้งานในปัจจุบันค่อนข้างอนุรักษ์นิยมกับการรับประกันการแสดงผล
เช่น การใช้ฟิลเตอร์โทนสีเทาที่แทบมองไม่เห็น เช่น filter: grayscale(0.01%)
หรือการตั้งค่าความโปร่งใสที่แทบมองไม่เห็นด้วย opacity: 0.99
จะทำให้องค์ประกอบนั้นมองไม่เห็น
ด้านล่างนี้คือตัวอย่างโค้ดสั้นๆ ที่แสดงฟีเจอร์ API ใหม่ คุณสามารถดูการทำงานของตรรกะการติดตามการคลิกในส่วนที่ 2 ของเดโม (แต่ตอนนี้ลอง "ดู" วิดีโอลูกสุนัข) อย่าลืมเปิดใช้งาน "โหมดกลโกง" อีกครั้งเพื่อเปลี่ยนตัวเองเป็นผู้เผยแพร่โฆษณาที่ไม่น่าไว้วางใจทันที และดูว่า Intersection Observer v2 ป้องกันไม่ให้มีการติดตามการคลิกโฆษณาที่เป็นการฉ้อโกงได้อย่างไร คราวนี้ Intersection Observer v2 จะช่วยเราได้ 🎉
<!DOCTYPE html>
<!-- This is the ad running in the iframe -->
<button id="callToActionButton">Buy now!</button>
// This is code running in the iframe.
// The iframe must be visible for at least 800ms prior to an input event
// for the input event to be considered valid.
const minimumVisibleDuration = 800;
// Keep track of when the button transitioned to a visible state.
let visibleSince = 0;
const button = document.querySelector('#callToActionButton');
button.addEventListener('click', (event) => {
if ((visibleSince > 0) &&
(performance.now() - visibleSince >= minimumVisibleDuration)) {
trackAdClick();
} else {
rejectAdClick();
}
});
const observer = new IntersectionObserver((changes) => {
for (const change of changes) {
// ⚠️ Feature detection
if (typeof change.isVisible === 'undefined') {
// The browser doesn't support Intersection Observer v2, falling back to v1 behavior.
change.isVisible = true;
}
if (change.isIntersecting && change.isVisible) {
visibleSince = change.time;
} else {
visibleSince = 0;
}
}
}, {
threshold: [1.0],
// 🆕 Track the actual visibility of the element
trackVisibility: true,
// 🆕 Set a minimum delay between notifications
delay: 100
}));
// Require that the entire iframe be visible.
observer.observe(document.querySelector('#ad'));
ลิงก์ที่เกี่ยวข้อง
- ฉบับร่างล่าสุดของข้อกำหนด Intersection Observer
- Intersection Observer v2 เปิดอยู่ สถานะ Chrome Platform
- ข้อบกพร่อง Chromium ของ Intersection Observer v2
- Blink ความตั้งใจในการติดตั้งใช้งานการโพสต์
ขอขอบคุณ
ขอขอบคุณ Simeon Vincent, Yoav Weiss และ Mathias Bynens ที่ตรวจสอบบทความนี้ รวมถึง Stefan Zager ที่ตรวจสอบและใช้งานฟีเจอร์นี้ใน Chrome รูปภาพหลักโดย Sergey Semin ใน Unsplash