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