ความเชื่อใจเป็นสิ่งที่ดี แต่การสังเกตการณ์ดีที่สุด: Intersection Observer v2

Browser Support

  • Chrome: 51.
  • Edge: 15.
  • Firefox: 55.
  • Safari: 12.1.

Source

Intersection Observer เป็นหนึ่งใน API ที่อาจเป็นที่ชื่นชอบของทุกคน และใช้ได้ในเบราว์เซอร์หลักๆ ทั้งหมด นักพัฒนาซอฟต์แวร์ใช้ API นี้สำหรับกรณีการใช้งานที่หลากหลาย รวมถึง การโหลดรูปภาพและวิดีโอแบบเลซีโหลด การแจ้งเตือนเมื่อองค์ประกอบถึง position: sticky การทริกเกอร์เหตุการณ์วิเคราะห์ และอื่นๆ อีกมากมาย

ในรูปแบบพื้นฐานที่สุด API ของ Intersection Observer v1 จะมีลักษณะดังนี้

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

API Intersection Observer เวอร์ชัน 1 ช่วยให้คุณทราบได้ว่าเมื่อใดที่องค์ประกอบเลื่อนเข้ามาใน Viewport ของหน้าต่าง อย่างไรก็ตาม คุณไม่สามารถระบุได้ว่าองค์ประกอบนั้นถูกเนื้อหาอื่นๆ ในหน้าเว็บครอบคลุมหรือไม่ ซึ่งเรียกว่าการบดบัง หรือองค์ประกอบนั้นปรากฏขึ้นโดยมีการแก้ไขด้วย CSS เช่น transform, opacity หรือ filter หรือไม่ ซึ่งอาจทําให้องค์ประกอบนั้นมองไม่เห็น

สำหรับองค์ประกอบในเอกสารระดับบนสุด คุณจะระบุข้อมูลนี้ได้โดยการวิเคราะห์ DOM ด้วย JavaScript เช่น DocumentOrShadowRoot.elementFromPoint() ในทางตรงกันข้าม คุณจะไม่สามารถรับข้อมูลเดียวกันได้หากองค์ประกอบที่เป็นปัญหาอยู่ใน iframe ของบุคคลที่สาม

เหตุใดการมองเห็นจึงสำคัญ

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

ผู้เผยแพร่โฆษณาอาจทำให้ iframe ของโฆษณามีความโปร่งใสโดยสมบูรณ์ด้วย CSS เพื่อหลอกลวงผู้ใช้ ดังนี้ iframe { opacity: 0; } จากนั้นก็วาง iframe แบบโปร่งใสเหล่านี้ซ้อนทับเนื้อหาที่น่าสนใจ เช่น วิดีโอแมวน่ารัก ซึ่งผู้ใช้ต้องการคลิก ซึ่งเรียกว่าการคลิกแจ็กกิ้ง

คุณสามารถดูการโจมตีแบบคลิกแจ็กกิ้งได้ในส่วนบนของเดโม ลอง "ดู" วิดีโอแมวและเปิดใช้งานโหมดเคล็ดลับ โฆษณาใน iframe จะบันทึกการคลิกว่าถูกต้อง แม้ว่าคุณจะคลิกโดยไม่ตั้งใจขณะที่ iframe โปร่งใสอยู่ก็ตาม

หลอกลวงให้ผู้ใช้คลิกโฆษณาโดยการจัดรูปแบบให้โปร่งใสและวางซ้อนไว้บนสิ่งที่น่าสนใจ

การปรับปรุงใน Intersection Observer เวอร์ชัน 2

Intersection Observer เวอร์ชัน 2 สามารถติดตาม "ระดับการเข้าถึง" ขององค์ประกอบตามที่มนุษย์ กำหนด หากคุณตั้งค่าตัวเลือกในIntersectionObserver Constructor อินสแตนซ์IntersectionObserverEntry ที่ได้จะมีช่องบูลีนใหม่ชื่อ isVisible เมื่อ isVisible เป็น true เบราว์เซอร์จะตรวจสอบว่าองค์ประกอบนั้นไม่มีเนื้อหาอื่น ปิดบังอยู่ และไม่มีเอฟเฟกต์ภาพที่ซ่อนหรือเปลี่ยนการแสดงผล หาก isVisibleเป็น false เบราว์เซอร์จะรับประกันไม่ได้

ข้อกำหนด อนุญาตให้มีผลลบลวง: isVisible อาจเป็น false แม้ว่าองค์ประกอบจะมองเห็นได้จริงและไม่เปลี่ยนแปลง เบราว์เซอร์จะใช้การคำนวณที่ง่ายกว่าเพื่อประสิทธิภาพ เช่น กรอบล้อมและรูปร่างสี่เหลี่ยมผืนผ้า และจะไม่ตรวจสอบทุกพิกเซลเพื่อหารายละเอียดที่ซับซ้อน เช่น border-radius

อย่างไรก็ตาม ไม่อนุญาตให้มีผลบวกลวงในทุกกรณี ซึ่งหมายความว่า isVisible จะไม่trueหากองค์ประกอบไม่ปรากฏอย่างสมบูรณ์ และไม่มีการแก้ไข

ใช้การเปลี่ยนแปลงเหล่านี้

ตอนนี้เครื่องมือสร้าง IntersectionObserver มีพร็อพเพอร์ตี้การกำหนดค่าเพิ่มเติม 2 รายการ ดังนี้

  • delay คือตัวเลขที่ระบุความล่าช้าขั้นต่ำในหน่วยมิลลิวินาทีระหว่าง การแจ้งเตือนจากผู้สังเกตการณ์สำหรับเป้าหมายที่กำหนด
  • trackVisibility เป็นบูลีนเพื่อระบุว่าผู้สังเกตการณ์จะติดตามการเปลี่ยนแปลง ระดับการเข้าถึงของเป้าหมายหรือไม่

เมื่อ trackVisibility เป็น true ต้องตั้งค่า delay เป็น 100 หรือค่าที่สูงกว่า (กล่าวคือ ไม่เกิน 1 การแจ้งเตือนทุกๆ 100 มิลลิวินาที) เนื่องจากความสามารถในการมองเห็นมีต้นทุนในการคำนวณสูง จึงต้องใช้มาตรการป้องกัน ประสิทธิภาพที่ลดลงและการใช้แบตเตอรี่ นักพัฒนาแอปที่มีความรับผิดชอบควร ใช้ค่าการหน่วงเวลาที่มากที่สุดที่ยอมรับได้

ข้อมูลจำเพาะ จะคำนวณระดับการมองเห็น เช่นเดียวกับเวอร์ชัน 1 เมื่อtrackVisibilityแอตทริบิวต์ของ Observer เป็น false ระบบจะถือว่าเป้าหมายมองเห็นได้

ในเวอร์ชัน 2 ระบบจะถือว่าเป้าหมายมองไม่เห็นในกรณีต่อไปนี้

  • มีเมทริกซ์การเปลี่ยนรูปแบบที่มีประสิทธิภาพ นอกเหนือจากการ แปล 2 มิติหรือการอัปสเกล 2 มิติแบบสัดส่วน

  • เป้าหมายหรือองค์ประกอบใดๆ ในบล็อกเชนที่มีเป้าหมายนั้นมีค่าความทึบแสงที่มีผลน้อยกว่า 1.0

  • เป้าหมายหรือองค์ประกอบใดๆ ในบล็อกเชนที่มีอยู่มีตัวกรอง ที่ใช้

  • หากการติดตั้งใช้งานไม่สามารถรับประกันได้ว่าเป้าหมายจะไม่ถูกเนื้อหาอื่นๆ ในหน้าเว็บบดบังโดยสมบูรณ์

ซึ่งหมายความว่าการใช้งานในปัจจุบันค่อนข้างระมัดระวังในการรับประกัน ระดับการมองเห็น เช่น การใช้ฟิลเตอร์ระดับสีเทาที่แทบจะมองไม่เห็น (filter: grayscale(0.01%)) หรือการตั้งค่าความโปร่งใสที่น้อยที่สุด (opacity: 0.99) จะทําให้องค์ประกอบมองไม่เห็น

นี่คือตัวอย่างโค้ดที่แสดงฟีเจอร์ใหม่ของ API คุณสามารถดูตรรกะการติดตามคลิกได้ในส่วนที่ 2 ของเดโม ลอง "ดู" วิดีโอลูกสุนัข เปิดใช้งานโหมดกลโกงเพื่อเปลี่ยนตัวเองเป็น ผู้ไม่ประสงค์ดีและดูว่า Intersection Observer v2 ป้องกัน การติดตามการคลิกโฆษณาที่ไม่ถูกต้องได้อย่างไร 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 v2, fallback 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'));

แหล่งข้อมูลเพิ่มเติม

การรับทราบ

ขอขอบคุณ Simeon Vincent, Yoav Weiss และ Mathias Bynens ที่ตรวจสอบ รวมถึงขอขอบคุณ Stefan Zager ที่ตรวจสอบและนำฟีเจอร์นี้ไปใช้ใน Chrome