การแสดงเนื้อหาแบบอินเทอร์แอกทีฟ

เพิ่มเอฟเฟกต์การเปิดเผยแบบอินเทอร์แอกทีฟที่มีประสิทธิภาพลงในเว็บไซต์ด้วยมาสก์ CSS และคุณสมบัติที่กำหนดเองที่ลงทะเบียนไว้ การใช้การไล่ระดับสีแบบรัศมีเป็นมาสก์และลงทะเบียนค่าหยุดจะช่วยให้เราเปลี่ยนผ่านการเข้าและออกได้อย่างราบรื่น ขณะเดียวกันก็ติดตามเคอร์เซอร์ของผู้ใช้ด้วย JavaScript เพียงเล็กน้อย

การใช้งาน

1. ลงทะเบียนคุณสมบัติที่กำหนดเอง

หากต้องการเปิดใช้การประมาณค่าในช่วงที่ราบรื่นของค่าจุดหยุดการไล่ระดับสี คุณต้องลงทะเบียนตัวแปรโดยใช้ @property ซึ่งจะแจ้งเครื่องมือของเบราว์เซอร์เกี่ยวกับประเภทข้อมูล เพื่อให้สามารถเปลี่ยนค่าระหว่างการอัปเดตได้

/* Register the spotlight inner and outer sizes to enable interpolation */
 @property --inner-size{
  syntax: "<length-percentage>";
  inherits: true;
  initial-value: 0px;
}
@property --outer-size{
  syntax: "<length-percentage>";
  inherits: true;
  initial-value: 0px;
}

คุณสมบัติที่กำหนดเองซึ่งติดตามตำแหน่งเคอร์เซอร์ไม่จำเป็นต้องเปลี่ยนสถานะ จึงไม่จำเป็นต้องลงทะเบียน

2. กำหนดเลเยอร์มาสก์

ใช้ mask-image กับองค์ประกอบที่ต้องการแสดง ใช้ radial-gradient ที่อ้างอิงพร็อพเพอร์ตี้ที่ลงทะเบียนไว้

.reveal-layer {
  /* Only transition the size properties, NOT the position variables */
  transition: --inner-size 0.2s ease-in-out, --outer-size 0.2s ease-in-out;  

  /* The spotlight is defined by the transparent center of the mask */
  mask-image: radial-gradient(
    circle at var(--mouse-x) var(--mouse-y),
    black var(--inner-size, 0%),
    transparent var(--outer-size, 0%)
  );

  /* Ensure the mask doesn't repeat if the element is large */
  mask-repeat: no-repeat;

  /* Make the mask layer non-interactive */
  pointer-events: none;
}

/* Update the gradients stops on interaction */
.reveal-layer:hover {
  --inner-size: 100px;
  --outer-size: 120px;
}  

3. อัปเดตพิกัดด้วย JavaScript

ติดตามตำแหน่งเคอร์เซอร์และอัปเดตตัวแปร CSS เนื่องจากมีการลงทะเบียนพร็อพเพอร์ตี้และกำหนด transition ไว้ สปอตไลท์จึงจะเคลื่อนที่อย่างราบรื่นแม้ว่าเหตุการณ์เคอร์เซอร์จะเกิดขึ้นไม่บ่อยนัก

const container = document.querySelector('.container');
// Store the container's bounding rect
let rect = container.getBoundingClientRect();
// Update the rect when the container is resized
const resizeObserver = new ResizeObserver(()=>{
  rect = container.getBoundingClientRect();
})
resizeObserver.observe(container);

container.addEventListener('pointermove', (e) => {
  // Calculate position as a percentage of the container.
  const x = ((e.clientX - rect.left) / rect.width) * 100;
  const y = ((e.clientY - rect.top) / rect.height) * 100;

  // Update the registered properties
  container.style.setProperty('--mouse-x', `${x}%`);
  container.style.setProperty('--mouse-y', `${y}%`);
});

4. การช่วยเหลือพิเศษและการโต้ตอบ

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

  • เหตุการณ์ตัวชี้: ตั้งค่า pointer-events: none ในเลเยอร์การวางซ้อนมาสก์เพื่อให้การโต้ตอบด้วยการคลิกและการแตะมาตรฐานส่งผ่านไปยังตัวควบคุมที่อยู่ด้านล่างได้
  • การลบล้างการเคลื่อนไหวที่ลดลง: ปิดใช้การประมาณค่าในช่วงการเปลี่ยนภาพที่ราบรื่นสำหรับผู้ใช้ที่ขอการเคลื่อนไหวที่ลดลง
/* MANDATORY Copy-Paste Safety: Disable transition scaling for motion-sensitive users */
@media (prefers-reduced-motion: reduce) {
  .reveal-layer {
    transition: none !important;
  }
}

กลยุทธ์สำรอง

โฆษณาสำรองสำหรับที่พักที่ไม่ได้ลงทะเบียน

เบราว์เซอร์ที่รองรับ mask-image แต่ไม่รองรับ @property จะยังคงแสดงสปอตไลท์ แต่การเคลื่อนไหวจะสลับไปมาระหว่างสถานะเปิดและปิดเนื่องจากไม่สามารถประมาณค่าภายใน radial-gradient ได้ ระบุค่าสำรองเมื่อใช้ var()

.reveal-layer {
  mask-image: radial-gradient(
    circle at var(--mouse-x) var(--mouse-y),
    /* Use fallback values when using the `var()` function for browsers that don't get an initial value from the @property registration. */
    black var(--inner-size, 0%),
    transparent var(--outer-size, 0%)
  );
}

การรองรับมาสก์พื้นฐาน

สำหรับเบราว์เซอร์ที่ไม่รองรับการมาสก์ CSS เลย ให้ทำดังนี้

  1. พร็อพเพอร์ตี้ที่มีคำนำหน้า: ใช้พร็อพเพอร์ตี้ที่มีคำนำหน้า -webkit-mask-image เพื่อให้เบราว์เซอร์รองรับได้มากขึ้น
  2. การเพิ่มประสิทธิภาพแบบต่อเนื่อง: ออกแบบสถานะพื้นฐานของ UI ให้ทำงานได้อย่างสมบูรณ์และอ่านได้โดยไม่ต้องใช้เอฟเฟกต์การแสดงผล ซึ่งจะมีประโยชน์เมื่อเอฟเฟกต์เป็นเพียงการเพิ่มลูกเล่นด้านภาพเท่านั้น และไม่ใช่ข้อกำหนดสำหรับการอ่านเนื้อหา