เจาะลึก CSS - matrix3d() สำหรับแถบเลื่อนที่กำหนดเองแบบเฟรมที่สมบูรณ์แบบ

แถบเลื่อนที่กำหนดเองทำได้ยากมาก และส่วนใหญ่แล้วก็เป็นเพราะว่าแถบเลื่อนเป็นส่วนเล็กๆ ที่เหลือบนเว็บซึ่งไม่ค่อยมีรูปแบบ (ฉันกำลังดูคุณอยู่ เครื่องมือเลือกวันที่) คุณใช้ JavaScript เพื่อสร้างโค้ดของตัวเองได้ ซึ่งมีค่าใช้จ่ายสูง ความแม่นยำต่ำ และอาจทำให้รู้สึกหน่วง ในบทความนี้ เราจะใช้ประโยชน์จากเมทริกซ์ CSS ที่ไม่เป็นมาตรฐานเพื่อสร้างตัวเลื่อนที่กำหนดเอง ซึ่งไม่ต้องใช้ JavaScript ขณะเลื่อน แต่ใช้เพียงโค้ดการตั้งค่าบางอย่างเท่านั้น

สรุปคร่าวๆ

คุณไม่ค่อยใส่ใจกับสิ่งเล็กๆ น้อยๆ เลยหรือ คุณแค่อยากดู การสาธิต Nyan Cat และรับคลังใช่ไหม ดูโค้ดของการสาธิตได้ในที่เก็บ GitHub ของเรา

LAM;WRA (แบบยาวและคณิตศาสตร์; จะอ่านอยู่แล้ว)

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

สรุป

มาเริ่มกันด้วยการสรุปวิธีการทำงานของแถบเลื่อนพารัลแลกซ์

ดังที่แสดงในภาพเคลื่อนไหว เราได้รับเอฟเฟกต์พารัลแลกซ์จากการผลักองค์ประกอบ "ย้อนกลับ" ในพื้นที่ 3 มิติตามแกน Z การเลื่อนเอกสารเป็นการแปลตามแกน Y อย่างมีประสิทธิภาพ ดังนั้นหากเราเลื่อนลง สมมติว่ามี 100 พิกเซล ทุกองค์ประกอบจะได้รับการแปลขึ้น 100 พิกเซล ซึ่งรวมถึงองค์ประกอบทั้งหมด รวมถึงองค์ประกอบที่ "อยู่ด้านหลัง" แต่เนื่องจากองค์ประกอบอยู่ห่างจากกล้อง การเคลื่อนไหวบนหน้าจอที่สังเกตได้จึงน้อยกว่า 100 พิกเซล ทำให้ได้เอฟเฟ็กต์พารัลแลกซ์ที่ต้องการ

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

ขั้นตอนที่ 0: คุณต้องการทำอะไร

แถบเลื่อน นั่นเป็นสิ่งที่เรากำลังจะสร้าง แล้วคุณเคยคิดจริงๆ ไหมว่า พวกเขาทำอะไร ไม่ใช่แน่นอน แถบเลื่อนเป็นสัญญาณบอกสถานะปริมาณเนื้อหาที่อ่านได้ในขณะนี้และความคืบหน้าที่ผู้อ่านทำได้ หากคุณเลื่อนลง แถบเลื่อนจะแสดงว่า คุณกำลังคืบหน้าไปจนสุด หากเนื้อหาทั้งหมดพอดีกับวิวพอร์ต แถบเลื่อนมักจะซ่อนอยู่ หากเนื้อหามีความสูง 2 เท่าของวิวพอร์ต แถบเลื่อนจะมีขนาดเท่ากับ 1⁄2 ของความสูงของวิวพอร์ต เนื้อหาที่มีมูลค่า 3 เท่าของความสูงของวิวพอร์ตจะปรับขนาดแถบเลื่อนเป็น 1⁄3 ของวิวพอร์ต และอื่นๆ คุณจะเห็นรูปแบบ แทนที่จะต้องเลื่อน คุณยังสามารถคลิกและลากแถบเลื่อนเพื่อไปยังส่วนต่างๆ ของเว็บไซต์ได้เร็วขึ้น นี่เป็นพฤติกรรมที่น่าประหลาดใจสำหรับองค์ประกอบที่ไม่ชัดเจนแบบนั้น ต่อสู้กันทีละศึก

ขั้นตอนที่ 1: สลับรูปแบบเดิมกลับ

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

หากต้องการดูการฉายภาพของมุมมองใดก็ตามในทางคณิตศาสตร์ คุณควรใช้พิกัดแบบเดียวกัน ผมจะไม่ลงรายละเอียดว่าข้อมูลนี้คืออะไรและทำไมถึงใช้งานได้ แต่คุณมองว่านี่เป็นพิกัด 3 มิติที่มีพิกัดเพิ่มอีก 4 ตัวที่เรียกว่า w พิกัดนี้ควรเป็น 1 ยกเว้นกรณีที่คุณต้องการทำให้มุมมองบิดเบี้ยว เราไม่ต้องกังวลเกี่ยวกับรายละเอียดของ w เนื่องจากเราจะไม่ใช้ค่าอื่นใดนอกจาก 1 ดังนั้นจากนี้จุดทั้งหมดจึงมาจากเวกเตอร์ 4 มิติ [x, y, z, w=1] และเมทริกซ์จึงต้องเป็น 4x4 เช่นกัน

มีครั้งหนึ่งที่คุณจะเห็นว่า CSS ใช้พิกัดแบบเอกพันธ์เบื้องหลังคือเมื่อคุณกำหนดเมทริกซ์ 4x4 ของคุณเองในคุณสมบัติ Transform โดยใช้ฟังก์ชัน matrix3d() matrix3d รับอาร์กิวเมนต์ 16 รายการ (เพราะเมทริกซ์คือ 4x4) โดยจะระบุคอลัมน์หนึ่งหลังจากอีกคอลัมน์ เราจึงสามารถใช้ฟังก์ชันนี้เพื่อระบุการหมุน การแปล ฯลฯ ด้วยตนเองได้ แต่สิ่งที่มันยังช่วยให้เราทำได้ก็คือยุ่งกับพิกัด w นั้น!

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

โค้ด CSS ที่บิดเบือน div โดยใช้แอตทริบิวต์มุมมองของ CSS

องค์ประกอบภายในคอนเทนเนอร์มุมมองจะได้รับการประมวลผลโดยเครื่องมือ CSS ดังนี้

  • เปลี่ยนแต่ละมุม (จุดยอด) ขององค์ประกอบเป็นพิกัดเดียวกัน [x,y,z,w] เมื่อเทียบกับคอนเทนเนอร์มุมมอง
  • ใช้การแปลงขององค์ประกอบทั้งหมดเป็นเมทริกซ์จากขวาไปซ้าย
  • หากองค์ประกอบมุมมองเลื่อนได้ ให้ใช้เมทริกซ์การเลื่อน
  • ใช้เมทริกซ์มุมมอง

เมทริกซ์การเลื่อนคือการแปลตามแกน Y หากเราเลื่อนลง 400 พิกเซล องค์ประกอบทั้งหมดจะต้องเลื่อนขึ้น 400 พิกเซล เมทริกซ์มุมมองคือเมทริกซ์ที่ "ดึง" ชี้ขึ้นใกล้กับจุดที่สูญหายไปมากขึ้นอีกในรัศมี 3 มิติ ซึ่งทั้ง 2 อย่างนี้ทำได้ทั้ง 2 อย่างคือการทำให้สิ่งต่างๆ ดูเล็กลงเมื่อถอยออกมาให้ห่างจากและ "เคลื่อนไหวช้าลง" ขณะแปลด้วย ดังนั้นหากองค์ประกอบถูกดันกลับ การแปลรหัส 400 พิกเซลจะทำให้องค์ประกอบเคลื่อนบนหน้าจอเพียง 300 พิกเซล

หากต้องการทราบรายละเอียดทั้งหมด ให้อ่านspecของโมเดลการแสดงผลการเปลี่ยนรูปแบบของ CSS แต่สำหรับบทความนี้ เราได้ทำให้อัลกอริทึมข้างต้นเข้าใจง่ายขึ้น

กล่องของเราอยู่ในคอนเทนเนอร์มุมมองที่มีค่า p สำหรับแอตทริบิวต์ perspective และสมมติว่าคอนเทนเนอร์สามารถเลื่อนได้และเลื่อนลงไป n พิกเซล

เมทริกซ์มุมมองคูณเมทริกซ์การเลื่อนคูณกับเมทริกซ์การแปลงขององค์ประกอบเท่ากับ 4 คูณ 4 เมทริกซ์เอกลักษณ์ที่มีลบ 1 โอเวอร์ p ในแถวที่ 3 ในคอลัมน์ที่ 3 คูณ 4 คูณ 4 เมทริกซ์อัตลักษณ์ที่มีลบ n ในคอลัมน์ที่ 4 คูณเมทริกซ์การแปลงองค์ประกอบ

เมทริกซ์แรกคือเมทริกซ์มุมมอง เมทริกซ์ที่สองคือเมทริกซ์การเลื่อน สรุปก็คือ หน้าที่ของเมทริกซ์การเลื่อนคือการทำให้องค์ประกอบเลื่อนขึ้นเมื่อเราเลื่อนลง นั่นจึงเป็นเครื่องหมายลบ

อย่างไรก็ตาม สำหรับแถบเลื่อนเราอยากให้อยู่ฝั่งตรงข้ามคือต้องการให้องค์ประกอบเลื่อนลงเมื่อเลื่อนลง นี่คือจุดที่เราสามารถใช้เคล็ดลับได้: การกลับพิกัด w ของมุมกล่อง หากพิกัด w เป็น -1 คำแปลทั้งหมดจะมีผลในทิศทางตรงกันข้าม แล้วเราทำอย่างไรล่ะ เครื่องมือ CSS จะดูแลการแปลงมุมของกล่องให้เป็นพิกัดแบบเดียวกัน และตั้งค่า w เป็น 1 ถึงเวลาที่ matrix3d() จะเปล่งประกาย

.box {
  transform:
    matrix3d(
      1, 0, 0, 0,
      0, 1, 0, 0,
      0, 0, 1, 0,
      0, 0, 0, -1
    );
}

เมทริกซ์นี้จะทำอะไรอย่างอื่นนอกจากการปฏิเสธ w ดังนั้นเมื่อเครื่องมือ CSS เปลี่ยนแต่ละมุมให้เป็นเวกเตอร์ของรูปแบบ [x,y,z,1] เมทริกซ์จะแปลงมุมเป็น [x,y,z,-1]

เมทริกซ์เอกลักษณ์ 4 คูณ 4 ที่มีลบ 1 โอเวอร์ p ในแถวที่ 4 คอลัมน์ที่ 3 คูณ 4 คูณ 4 เมทริกซ์อัตลักษณ์ที่มีลบ n ในคอลัมน์ที่ 2 แถวที่ 4 คูณ 4 คูณ 4 เมทริกซ์ข้อมูลประจำตัวโดยมี -1 ลบ 1 ในคอลัมน์ที่ 4 คูณเวกเตอร์ที่มีมิติ x, y, z, 1 เท่ากับ 4
 คูณ 4 เมทริกซ์ประจำตัวในแถวที่ 4 บวกกับ 1 แถว n ในแถวที่ 4 ลบด้วย 1 ในแถวที่ 4 คูณเวกเตอร์มิติที่ x, y, z, 1 เท่ากับ 4
 คูณ 4 เมทริกซ์ในแถวที่ 2 ลบด้วย 1 แถว n ในแถวที่ 4

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

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

โชคดีที่เราเลือกค่า z ได้ เพื่อให้แน่ใจว่าเราได้ค่า w=1 เราต้อง ตั้ง z = -2

.box {
  transform:
    matrix3d(
      1, 0, 0, 0,
      0, 1, 0, 0,
      0, 0, 1, 0,
      0, 0, 0, -1
    )
    translateZ(-2px);
}

โลว่า กล่องของเรากลับมาแล้ว!

ขั้นตอนที่ 2: เคลื่อนไหวได้

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

<div class="container">
    <div class="box"></div>
    <span class="spacer"></span>
</div>

<style>
/* … all the styles from the previous example … */
.container {
    overflow: scroll;
}
.spacer {
    display: block;
    height: 500px;
}
</style>

และตอนนี้ เลื่อนกล่อง! กล่องสีแดงจะเลื่อนลง

ขั้นตอนที่ 3: กำหนดขนาด

เรามีองค์ประกอบที่เลื่อนลงเมื่อหน้าเว็บเลื่อนลง จริงๆ แล้วนั่นเป็นไอเดียที่ยากมาก คราวนี้เราต้องปรับสไตล์ให้เหมือนแถบเลื่อน และทำให้มีการโต้ตอบมากขึ้น

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

<script>
    const scroller = document.querySelector('.container');
    const thumb = document.querySelector('.box');
    const scrollerHeight = scroller.getBoundingClientRect().height;
    thumb.style.height = /* ??? */;
</script>

scrollerHeight คือความสูงขององค์ประกอบที่เลื่อนได้ ขณะที่ scroller.scrollHeight คือความสูงรวมของเนื้อหาที่เลื่อนได้ scrollerHeight/scroller.scrollHeight คือเศษส่วนของเนื้อหาที่ปรากฏ อัตราส่วนของพื้นที่แนวตั้งที่นิ้วโป้งครอบควรเท่ากับอัตราส่วนของเนื้อหาที่มองเห็นได้ ดังนี้

รูปแบบจุดนิ้วหัวแม่มือแบบจุดเหนือ ScrollerHeight เท่ากับความสูงของตัวเลื่อนเหนือความสูงในการเลื่อนของจุดของตัวเลื่อน หากและก็ต่อเมื่อเมื่อรูปแบบจุดนิ้วหัวแม่มือเป็นจุดความสูงของจุด
 เท่ากับความสูงของตัวเลื่อนคูณความสูงของตัวเลื่อนเหนือความสูงในการเลื่อนของจุดของการเลื่อน
<script>
    // …
    thumb.style.height =
    scrollerHeight * scrollerHeight / scroller.scrollHeight + 'px';
    // Accommodate for native scrollbars
    thumb.style.right =
    (scroller.clientWidth - scroller.getBoundingClientRect().width) + 'px';
</script>

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

ข้อมูลที่สำคัญคือเราอยากให้ขอบด้านล่างของนิ้วโป้งอยู่ในแนวเดียวกับขอบด้านล่างขององค์ประกอบที่เลื่อนได้เมื่อเลื่อนลงจนสุด กล่าวคือ หากเราเลื่อน scroller.scrollHeight - scroller.height พิกเซล เราต้องการให้แปลนิ้วโป้ง เป็น scroller.height - thumb.height สำหรับตัวเลื่อนทุกๆ พิกเซล เราอยาก ให้นิ้วโป้งเคลื่อนที่เพียงเศษเสี้ยวของพิกเซล

ตัวประกอบเท่ากับความสูงของจุดตัวเลื่อนลบกับความสูงของจุดนิ้วหัวแม่มือเหนือตัวเลื่อน
  ความสูงของจุดเลื่อนลบกับความสูงของจุดแถบเลื่อน

นี่คือปัจจัยด้านการปรับขนาดของเรา ตอนนี้เราต้องแปลงตัวคูณมาตราส่วนเป็นการแปลตามแกน z ซึ่งเราทำไปแล้วในบทความการเลื่อนพารัลแลกซ์ ส่วนที่เกี่ยวข้องในข้อกำหนดระบุว่าค่าตัวคูณมาตราส่วนเท่ากับ p/(p − z) เราสามารถแก้สมการของ z เพื่อหาจำนวนที่เราต้องแปลนิ้วโป้งไปตามแกน z แต่โปรดทราบว่าเนื่องจากเราต้องใช้พิกัดของพิกัด เราจึงต้องแปล -2px เพิ่มเติมตาม z นอกจากนี้ โปรดทราบว่าการแปลงองค์ประกอบจะมีผล จากขวาไปซ้าย ซึ่งหมายความว่าการแปลทั้งหมดก่อนหน้าเมทริกซ์พิเศษของเราจะไม่ถูกกลับสี แต่การแปลทั้งหมดตามหลังเมทริกซ์พิเศษจะมีผล มาแปลงข้อมูลนี้กัน!

<script>
    // ... code from above...
    const factor =
    (scrollerHeight - thumbHeight)/(scroller.scrollHeight - scrollerHeight);
    thumb.style.transform = `
    matrix3d(
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, -1
    )
    scale(${1/factor})
    translateZ(${1 - 1/factor}px)
    translateZ(-2px)
    `;
</script>

เรามี scrollbar! และเป็นเพียงองค์ประกอบ DOM ที่เราสามารถจัดรูปแบบได้ตามที่ต้องการ สิ่งหนึ่งที่สำคัญที่ต้องทำในแง่ของการเข้าถึงคือการทำให้นิ้วหัวแม่มือตอบสนองต่อการคลิกและลาก เนื่องจากผู้ใช้หลายคนเคยชินกับการโต้ตอบกับแถบเลื่อนด้วยวิธีนี้ เพื่อไม่ให้การโพสต์บล็อกนี้ยาวขึ้น เราจะไม่อธิบายรายละเอียดของส่วนนั้น ดูรายละเอียด ในโค้ดไลบรารีเพื่อดูวิธีการทำงาน

แล้ว iOS ล่ะ

โอ้ เพื่อนเก่า iOS Safari เราพบปัญหาตรงนี้ เช่นเดียวกับการเลื่อนพารัลแลกซ์ เนื่องจากเราจะเลื่อนบนองค์ประกอบ เราต้องระบุ -webkit-overflow-scrolling: touch แต่นั่นทำให้การปรับ 3D แบบแบนราบและเอฟเฟกต์การเลื่อนทั้งหมดของเราจะหยุดทำงาน เราแก้ปัญหานี้ในแถบเลื่อนพารัลแลกซ์โดยการตรวจหา iOS Safari และใช้ position: sticky เป็นวิธีแก้ปัญหาเบื้องต้น และเราจะดำเนินการเช่นเดียวกันนี้ที่นี่ โปรดดูบทความเกี่ยวกับพารัลแลกซ์เพื่อรีเฟรชความทรงจำ

แล้วแถบเลื่อนของเบราว์เซอร์จะเป็นอย่างไร

ในบางระบบ เราจะต้องจัดการกับแถบเลื่อนของระบบอย่างถาวร ก่อนหน้านี้ คุณจะซ่อนแถบเลื่อนไม่ได้ (ยกเว้นเมื่อมีตัวเลือกเทียมที่ไม่เป็นมาตรฐาน) ด้วยเหตุนี้เราจึงต้องพึ่งพาการแฮ็ก (ไม่ต้องใช้คณิตศาสตร์) เรารวมองค์ประกอบแบบเลื่อนไว้ในคอนเทนเนอร์ที่มี overflow-x: hidden และทำให้องค์ประกอบที่เลื่อนได้กว้างกว่าคอนเทนเนอร์ แถบเลื่อนเดิมของเบราว์เซอร์จะมองไม่เห็นแล้ว

เสร็จสิ้น

เมื่อนำทุกอย่างมารวมกันแล้ว คุณก็สามารถสร้างแถบเลื่อนที่กำหนดเอง แบบเฟรมที่สมบูรณ์แบบ เหมือนกับใน การสาธิตแมว Nyan ของเรา

หากคุณไม่เห็นแมว Nyan แสดงว่ามีข้อบกพร่องที่เราพบและยื่นขณะสร้างการสาธิตนี้ (คลิกนิ้วโป้งเพื่อให้แมว Nyan ปรากฏขึ้น) Chrome สามารถหลีกเลี่ยงงานที่ไม่จำเป็น เช่น การทาสีหรือการทำให้สิ่งที่อยู่นอกหน้าจอเคลื่อนไหวได้เป็นอย่างดี ข่าวร้ายคือ เฉิดฉายเดอะเมทริกซ์ของเราทำให้ Chrome คิดว่า GIF แมว Nyan ไม่ได้อยู่บนหน้าจอ หวังว่าปัญหานี้จะได้รับการแก้ไขในเร็วๆ นี้

เสร็จแล้วครับ ซึ่งเป็นงานหนักมาก ขอชื่นชมที่คุณ อ่านจนจบเลย นี่เป็นวิธีการที่ซับซ้อนและไม่ค่อยคุ้มค่านัก ยกเว้นในกรณีที่แถบเลื่อนที่กำหนดเองเป็นส่วนสำคัญของประสบการณ์การใช้งาน แต่ก็ดีนะที่ได้รู้ว่ามันเป็นไปได้ ไม่นะ การที่แถบเลื่อนที่กำหนดเองทำได้ยากแสดงว่ายังมีงานที่ต้องทำในฝั่งของ CSS แต่ไม่ต้องกลัว ส่วนในอนาคต AnimationWorklet ของ Houdini จะทำ เอฟเฟกต์แบบลิงก์การเลื่อนที่เฟรมที่สมบูรณ์แบบเช่นนี้ได้ง่ายขึ้นมาก