เผยแพร่: 26 กุมภาพันธ์ 2026
ภาพเคลื่อนไหวที่ทำงานตามการเลื่อนได้พัฒนาจากการใช้งาน JavaScript ในเธรดหลักที่กระตุกเป็นประสบการณ์การใช้งานที่ราบรื่นและเข้าถึงได้นอกเธรดหลักโดยใช้ฟีเจอร์ CSS และ UI ที่ทันสมัย เช่น ไทม์ไลน์การเลื่อนและไทม์ไลน์มุมมอง การเปลี่ยนแปลงนี้ช่วยให้สร้างต้นแบบได้อย่างรวดเร็วและสร้างภาพเคลื่อนไหวที่มีประสิทธิภาพสูง ทั้งยังช่วยให้ทีมสร้างหน้าการเล่าเรื่องแบบเลื่อนที่สมบูรณ์แบบได้ดังที่แสดงในบทความนี้
NRK และการเล่าเรื่อง
NRK (Norwegian Broadcasting Corporation) เป็นผู้ออกอากาศบริการสาธารณะในนอร์เวย์ ทีมที่อยู่เบื้องหลังการใช้งานที่อธิบายไว้ในบทความนี้เรียกว่า Visuelle Historier ในภาษานอร์เวย์ ซึ่งแปลเป็นภาษาอังกฤษคร่าวๆ ว่า Visual Stories ทีมนี้ทำงานเกี่ยวกับการออกแบบ กราฟิก และการพัฒนาโปรเจ็กต์ด้านบรรณาธิการสำหรับทีวี วิทยุ และเว็บ โดยพัฒนาเอกลักษณ์ทางภาพ กราฟิกเนื้อหา บทความแนะนำ และรูปแบบการเล่าเรื่องด้วยภาพใหม่ๆ นอกจากนี้ ทีมยังทำงานร่วมกับโปรไฟล์การออกแบบและแบรนด์ย่อยของ NRK รวมถึงสร้างเครื่องมือและเทมเพลตเพื่อให้เผยแพร่เนื้อหาตามเอกลักษณ์ของแบรนด์ NRK ได้ง่ายขึ้น
วิธีที่ NRK ใช้ภาพเคลื่อนไหวที่ทำงานตามการเลื่อน
ภาพเคลื่อนไหวที่ทำงานตามการเลื่อนและที่ทำงานเมื่อมีการเลื่อนจะช่วยเพิ่มประสิทธิภาพการเล่าเรื่องในบทความด้วยการทำให้เป็นบทความแบบอินเทอร์แอกทีฟ น่าสนใจ และน่าจดจำมากขึ้น แนวทางนี้มีประโยชน์อย่างยิ่งในเนื้อหาสารคดีที่มีรูปภาพเพียงไม่กี่รูปหรือไม่มีเลย
ภาพเคลื่อนไหวเหล่านี้ช่วยเสริมหรือสร้างจุดสำคัญของเรื่อง ขับเคลื่อนเรื่องราวให้ดำเนินต่อไป และสร้างการเล่าเรื่องด้วยภาพเล็กๆ น้อยๆ ที่สอดคล้องกับหรือเสริมข้อความ ภาพเคลื่อนไหวเหล่านี้จะทำงานตามการเลื่อน ทำให้ผู้ใช้ควบคุมความคืบหน้าของเรื่องเล่าได้ด้วยการเลื่อน
ยกระดับประสบการณ์ของผู้ใช้
ข้อมูลเชิงลึกของผู้ใช้ NRK แสดงให้เห็นว่าผู้อ่านชื่นชอบวิธีที่ภาพเคลื่อนไหวเหล่านี้ช่วยกำหนดจุดสนใจ การไฮไลต์ข้อความหรือภาพเคลื่อนไหวขณะที่ผู้ใช้เลื่อนดูจะช่วยให้ผู้ใช้ระบุประเด็นสำคัญและทำความเข้าใจแง่มุมที่สำคัญที่สุดของเรื่องราวได้ง่ายขึ้น โดยเฉพาะเมื่ออ่านผ่านๆ
นอกจากนี้ กราฟิกเคลื่อนไหวยังช่วยลดความซับซ้อนของข้อมูล ทำให้ผู้ใช้เข้าใจความสัมพันธ์และการเปลี่ยนแปลงเมื่อเวลาผ่านไปได้ง่ายขึ้น การสร้าง การเพิ่ม หรือไฮไลต์ข้อมูลแบบไดนามิกช่วยให้ NRK นำเสนอเนื้อหาในลักษณะที่เน้นการเรียนรู้และน่าสนใจยิ่งขึ้น
การสร้างบรรยากาศ
ภาพเคลื่อนไหวเป็นเครื่องมือที่มีประสิทธิภาพในการกำหนดหรือเพิ่มอารมณ์ของเรื่องราว การปรับเวลา ความเร็ว และสไตล์ของภาพเคลื่อนไหวช่วยให้ NRK กระตุ้นอารมณ์ที่ตรงกับโทนของเรื่องเล่าได้
แบ่งข้อความและทำให้ภาพดูสบายตา
NRK มักใช้ภาพเคลื่อนไหวขนาดเล็กเพื่อแบ่งบล็อกข้อความยาวๆ ในรูปแบบของภาพเล็กๆ ง่ายๆ ซึ่งช่วยให้ผู้อ่านหยุดพักจากการอ่านเรื่องราวได้ชั่วขณะ ผู้ใช้จำนวนมากชื่นชอบรูปแบบนี้ โดยระบุว่าเป็นการแบ่งข้อความออกเป็นส่วนๆ และทำให้อ่านง่ายขึ้น ผู้ชมรู้สึกว่าการหยุดชั่วคราวนี้ช่วยสร้างช่วงพักที่พอเหมาะในคําบรรยาย
เคารพความต้องการด้านการช่วยเหลือพิเศษและค่ากําหนดของผู้ใช้
หน้าสาธารณะของ NRK ต้องเข้าถึงได้สำหรับพลเมืองทุกรายของนอร์เวย์ ดังนั้น หน้าเว็บต้องเป็นไปตามความต้องการของผู้ใช้ในการลดการเคลื่อนไหว เนื้อหาหน้าเว็บทั้งหมดต้องพร้อมใช้งานสําหรับผู้ใช้ที่เปิดใช้การตั้งค่าเบราว์เซอร์นี้
การออกแบบภาพเคลื่อนไหวที่ทำงานตามการเลื่อน
NRK ได้ปรับปรุงเวิร์กโฟลว์การออกแบบโดยการพัฒนาและผสานรวมเครื่องมือภาพเคลื่อนไหวแบบเลื่อนใหม่เข้ากับระบบจัดการเนื้อหา (CMS) ของ Sanity โดยตรง เครื่องมือนี้พัฒนาขึ้นโดยความร่วมมือระหว่างทีมที่พัฒนาและดูแลรักษาเว็บไซต์และโซลูชัน CMS ซึ่งช่วยให้นักออกแบบสามารถสร้างต้นแบบและใช้งานภาพเคลื่อนไหวในการเลื่อนได้อย่างง่ายดายด้วยตัวช่วยแสดงภาพสำหรับตำแหน่งเริ่มต้นและสิ้นสุดขององค์ประกอบภาพเคลื่อนไหว รวมถึงสามารถดูตัวอย่างภาพเคลื่อนไหวแบบเรียลไทม์ นวัตกรรมนี้ช่วยให้นักออกแบบมีการควบคุมมากขึ้นและเร่งกระบวนการออกแบบได้โดยตรงภายใน CMS

ภาพเคลื่อนไหวที่ทำงานตามการเลื่อนในเบราว์เซอร์
ภาพเคลื่อนไหวที่เน้นเรื่องราว
บทความนี้เกี่ยวกับชายคนหนึ่งที่เสียชีวิตในอพาร์ตเมนต์เป็นเวลา 9 ปีต้องใช้ภาพประกอบเป็นอย่างมากเนื่องจากไม่มีองค์ประกอบภาพอื่นๆ ภาพประกอบมีภาพเคลื่อนไหวเมื่อเลื่อนเพื่อเน้นการเล่าเรื่อง เช่น ในภาพเคลื่อนไหวที่เวลาล่วงเลยเข้าสู่ช่วงกลางคืน ไฟในอาคารสูงหลายชั้นค่อยๆ เปิดขึ้นจนเหลือเพียงอพาร์ตเมนต์เดียวที่ยังไม่ได้เปิดไฟ ภาพเคลื่อนไหวสร้างขึ้นโดยใช้เครื่องมือภาพเคลื่อนไหวแบบเลื่อนที่ NRK พัฒนาขึ้นเอง
ภาพเคลื่อนไหวข้อความค่อยๆ จางหายไป
บทความนี้เริ่มต้นด้วยการแนะนำสั้นๆ ซึ่งเลียนแบบช่วงเปิดของภาพยนตร์ ข้อความที่กระชับซึ่งมาพร้อมกับภาพแบบเต็มหน้าจอได้รับการออกแบบมาเพื่อบอกใบ้ถึงเนื้อหาของบทความ สร้างความคาดหวังเพื่อกระตุ้นให้ผู้อ่านอ่านบทความฉบับเต็ม หน้าปกออกแบบมาให้คล้ายกับโปสเตอร์ภาพยนตร์ โดยมีการใช้ภาพเคลื่อนไหวที่ทำงานตามการเลื่อนเพื่อเสริมความรู้สึกนี้ด้วยการแสดงภาพข้อความขึ้นและออกอย่างราบรื่น
.article-section {
animation: fade-up linear;
animation-timeline: view();
animation-range: entry 100% exit 100%;
}
ตัวอักษรแบบเคลื่อนไหวตามการเลื่อน
ตัวอักษรเคลื่อนไหวในชื่อบทความ "ลาป่วย"
ในการแนะนำ "Sjukt sjuke" (แปลคร่าวๆ ว่า "ป่วยมาก") NRK ต้องการดึงดูดผู้อ่านให้อ่านบทความเกี่ยวกับอัตราการลาป่วยที่เพิ่มขึ้นในนอร์เวย์ ชื่อนี้มีไว้เพื่อดึงดูดสายตาของผู้อ่านและบอกเป็นนัยว่านี่ไม่ใช่เรื่องราวที่เน้นตัวเลขที่น่าเบื่อตามปกติที่พวกเขาอาจคาดหวัง ทีม NRK ต้องการให้ข้อความและภาพประกอบสื่อถึงธีมของผลงานโดยใช้แบบอักษรและภาพเคลื่อนไหวที่เลื่อนตาม บทความนี้ใช้แบบอักษรและโปรไฟล์การออกแบบใหม่ของ NRK News
<h1 aria-label="sjuke">
<span>s</span><span>j</span><span>u</span><span>k</span><span>e</span>
<h1>
h1 span {
display: inline-block;
}
if (window.matchMedia('print, (prefers-reduced-motion: reduce)').matches) {
return;
}
const heading = document.querySelector("h1");
const letters = heading.querySelectorAll("span");
const timeline = new ViewTimeline({ subject: heading });
const scales = [/**/];
const rotations = [/**/];
for ([index, el] of letters.entries()) {
el.animate(
{
scale: ["1", scales[index]],
rotate: ["0deg", rotations[index]]
},
{
timeline,
fill: "both",
rangeStart: "contain 30%",
rangeEnd: "contain 70%",
easing: "ease-out"
}
);
}
การไฮไลต์รายการที่เลื่อน
ผู้อ่านที่อ่านบทความจบแล้วมักต้องการอ่านเพิ่มเติมเกี่ยวกับปัญหาเดียวกัน ในบทความเกี่ยวกับเยาวชนที่เสพสารเสพติดในสถานดูแล NRK ต้องการแนะนำบทความเดียวให้อ่านต่อ ขณะเดียวกันก็ให้ตัวเลือกบทความอื่นๆ แก่ผู้อ่านด้วยหากต้องการ โซลูชันคือการนำทางแบบปัดที่ใช้การเลื่อนแบบ Snap และภาพเคลื่อนไหวที่ทำงานด้วยการเลื่อน ภาพเคลื่อนไหวช่วยให้แน่ใจว่าองค์ประกอบที่ใช้งานอยู่อยู่ในโฟกัส ขณะที่องค์ประกอบที่เหลือจะสลัวลง
for (let item of items) {
const timeline = new ViewTimeline({ subject: item, axis: "inline" });
const animation = new Animation(effect, timeline);
item.animate(
{
opacity: [0.3, 1, 0.3]
},
{ timeline, easing: "ease-in-out", fill: "both" }
);
animation.rangeStart = "cover calc(50% - 100px)";
animation.rangeEnd = "cover calc(50% + 100px)";
}
ภาพเคลื่อนไหวการเลื่อนที่ทริกเกอร์ภาพเคลื่อนไหวปกติ
ในบทความเกี่ยวกับงบประมาณแผ่นดินของนอร์เวย์นี้ NRK มุ่งมั่นที่จะทำให้เรื่องราวที่เกี่ยวกับตัวเลขซึ่งเข้าใจยากและน่าเบื่อเข้าถึงได้ง่ายขึ้นและเหมาะกับผู้อ่านแต่ละคนมากขึ้น เป้าหมายคือแจกแจงตัวเลขงบประมาณมหาศาลที่เข้าใจยาก และช่วยให้ผู้อ่านเห็นภาพว่าภาษีของตนถูกนำไปใช้ทำอะไรบ้าง ส่วนย่อยแต่ละส่วนมุ่งเน้นที่รายการหนึ่งๆ ในงบประมาณแห่งชาติ เงินภาษีทั้งหมดที่ได้จากยอดขายหนังสือของผู้ใช้แสดงด้วยแถบสีน้ำเงินที่แบ่งออกเป็นส่วนๆ เพื่อแสดงให้เห็นว่าผู้ใช้มีส่วนร่วมกับรายการเหล่านี้อย่างไร การเปลี่ยนทำได้ด้วยภาพเคลื่อนไหวที่ทำงานตามการเลื่อน ซึ่งจะทริกเกอร์ให้แต่ละรายการแสดงภาพเคลื่อนไหว
const timeline = new ViewTimeline({
subject: containerElement
});
// Setup scroll-driven animation
const scrollAnimation = containerElement.animate(
{
"--cover-color": ["blue", "lightblue"],
scale: ["1 0.2", "1 3"]
},
{
timeline,
easing: "cubic-bezier(1, 0, 0, 0)",
rangeStart: "cover 0%",
rangeEnd: "cover 50%"
}
);
// Wait for scroll-driven animation to complete
await scrollAnimation.finished;
scrollAnimation.cancel();
// Trigger time-driven animations
for (let [index, postElement] of postElements.entries()) {
const animation = postElement?.animate(
{ scale: ["1 3", "1 1"] },
{
duration: 200,
delay: index * 33,
easing: "ease-out",
fill: "backwards"
}
);
}
"เราใช้ภาพเคลื่อนไหวที่ทำงานตามการเลื่อนมาเป็นเวลานานแล้ว ก่อนหน้านี้เราต้องใช้เหตุการณ์การเลื่อน ซึ่งต่อมาได้รวมเข้ากับ Intersection Observer API การดำเนินการนี้มักจะใช้เวลานานมาก แต่ตอนนี้กลายเป็นเรื่องง่ายดายด้วย Web Animations และ Scroll-Driven Animations API" - Helge Silset นักพัฒนาซอฟต์แวร์ฝั่งเฟรมเวิร์ก (Front-end) ที่ NRK
NRK มีคอมโพเนนต์เว็บหลายรายการที่เสียบเข้ากับองค์ประกอบที่กำหนดเองอย่างใดอย่างหนึ่งได้ ซึ่งเรียกว่า ScrollAnimationDriver
(<scroll-animation-driver>
) ซึ่งรองรับภาพเคลื่อนไหวต่อไปนี้
- เลเยอร์ที่มี
[KeyframeEffects](https://developer.mozilla.org/docs/Web/API/KeyframeEffect)
- ภาพเคลื่อนไหว Lottie
- mp4
- three.js
<canvas>
ตัวอย่างต่อไปนี้ใช้เลเยอร์ที่มี KeyframeEffects
<scroll-animation-driver data-range-start='entry-crossing 50%' data-range-end='exit-crossing 50%'>
<layered-animation-effect>
<picture>
<source />
<img />
</picture>
<picture>
<source />
<img />
</picture>
<picture>
<source />
<img />
</picture>
</layered-animation-effect>
</scroll-animation-driver>
การใช้งาน JavaScript ของ NRK สำหรับ<scroll-animation-driver>
องค์ประกอบที่กําหนดเอง
export default class ScrollAnimationDriver extends HTMLElement {
#timeline
connectedCallback() {
this.#timeline = new ViewTimeline({subject: this})
for (const child of this.children) {
for (const effect of child.effects ?? []) {
this.#setupAnimationEffect(effect)
}
}
}
#setupAnimationEffect(effect) {
const animation = new Animation(effect, this.#timeline)
animation.rangeStart = this.rangeStart
animation.rangeEnd = this.rangeEnd
if (this.prefersReducedMotion) {
animation.currentTime = CSS.percent(this.defaultProgress * 100)
} else {
animation.play()
}
}
}
export default class LayeredAnimationEffect extends HTMLElement {
get effects() {
return this.layers.flatMap(layer => toKeyframeEffects(layer))
}
}
ประสิทธิภาพการเลื่อน
NRK ใช้งาน JavaScript ที่มีประสิทธิภาพสูงมากก่อนที่จะใช้ภาพเคลื่อนไหวที่ทำงานตามการเลื่อน แต่ตอนนี้ภาพเคลื่อนไหวที่ทำงานตามการเลื่อนช่วยให้มีประสิทธิภาพมากยิ่งขึ้นโดยไม่ต้องกังวลเรื่องการเลื่อนที่กระตุก แม้ในอุปกรณ์พลังงานต่ำ
- ระยะเวลาของงานที่ไม่ใช่ SDA: 1 มิลลิวินาที
- ระยะเวลาของงาน SDA: 0.16 มิลลิวินาที

หากต้องการอ่านเพิ่มเติมเกี่ยวกับความแตกต่างของประสิทธิภาพการเลื่อนระหว่างการติดตั้งใช้งาน JavaScript กับภาพเคลื่อนไหวที่ทำงานตามการเลื่อน โปรดอ่านบทความกรณีศึกษาเกี่ยวกับประสิทธิภาพของภาพเคลื่อนไหวที่ทำงานตามการเลื่อนซึ่งจะอธิบายรายละเอียดเพิ่มเติม
การช่วยเหลือพิเศษและข้อควรพิจารณาเกี่ยวกับ UX
การช่วยเหลือพิเศษมีบทบาทสำคัญในหน้าสาธารณะของ NRK เนื่องจากหน้าดังกล่าวต้องเข้าถึงได้สำหรับพลเมืองทุกรายของนอร์เวย์ในหลายๆ สถานการณ์ NRK ช่วยให้ผู้ใช้เข้าถึงภาพเคลื่อนไหวในการเลื่อนได้หลายวิธีดังนี้
- เคารพความต้องการของผู้ใช้ในการลดการเคลื่อนไหว: ใช้ Media Query
screen and (prefers-reduced-motion: no-preference)
เพื่อใช้ภาพเคลื่อนไหวเป็นการเพิ่มประสิทธิภาพแบบเป็นขั้นเป็นตอน ทั้งยังช่วยจัดการสไตล์การพิมพ์ได้ในเวลาเดียวกันด้วย - คำนึงถึงอุปกรณ์ที่หลากหลายและความละเอียดของอินพุตการเลื่อน: ผู้ใช้บางรายอาจเลื่อนทีละขั้น (Space หรือแป้นขึ้น/ลง การไปยังจุดสังเกตโดยใช้โปรแกรมอ่านหน้าจอ) และไม่เห็นภาพเคลื่อนไหวทั้งหมด ตรวจสอบว่าไม่พลาดข้อมูลสำคัญ
- ระมัดระวังการใช้ภาพเคลื่อนไหวที่แสดงหรือซ่อนเนื้อหา: ผู้ใช้ที่พึ่งพาการซูมของระบบปฏิบัติการ (OS) อาจสังเกตไม่เห็นว่าเนื้อหาที่ซ่อนอยู่จะปรากฏขึ้นขณะที่เลื่อนดู หลีกเลี่ยงการทําให้ผู้ใช้ต้องค้นหา หากจำเป็นต้องซ่อนหรือแสดงเนื้อหา ให้ตรวจสอบว่าตำแหน่งที่เนื้อหาปรากฏและหายไปมีความสอดคล้องกัน
- หลีกเลี่ยงการเปลี่ยนแปลงความสว่างหรือคอนทราสต์อย่างมากในภาพเคลื่อนไหว: เนื่องจากภาพเคลื่อนไหวที่ทำงานด้วยการเลื่อนขึ้นอยู่กับการควบคุมของผู้ใช้ การเปลี่ยนแปลงความสว่างอย่างฉับพลันจึงอาจดูเหมือนการกะพริบ ซึ่งอาจทำให้เกิดอาการชักในผู้ใช้บางราย
@media (prefers-reduced-motion: no-preference) {
.article-image {
opacity: 0;
transition: opacity 1s ease-in-out;
}
.article-image.visible {
opacity: 1;
}
}
การสนับสนุนเบราว์เซอร์
NRK ใช้ Polyfill แบบโอเพนซอร์สเพื่อรองรับเบราว์เซอร์ที่หลากหลายมากขึ้นสำหรับ ScrollTimeline และ ViewTimeline โดยมีชุมชนที่มีส่วนร่วมในการพัฒนา
ปัจจุบันระบบจะโหลด polyfill แบบมีเงื่อนไขเมื่อ ScrollTimeline
ไม่พร้อมใช้งานและใช้ polyfill เวอร์ชันที่ตัดความสามารถบางอย่างออกโดยไม่รองรับ CSS
if (!('ScrollTimeline' in window)) {
await import('scroll-timeline.js')
}
การตรวจหาและการรองรับเบราว์เซอร์ใน CSS
@supports not (animation-timeline: view()) {
.article-section {
translate: 0 calc(-15vh * var(--fallback-progress));
opacity: var(--fallback-progress);
}
}
@supports (animation-timeline: view()) {
.article-section {
animation: --fade-up linear;
animation-timeline: view();
animation-range: entry 100% exit 100%;
}
}
ในตัวอย่างก่อนหน้านี้สำหรับเบราว์เซอร์ที่ไม่รองรับ NRK ใช้ตัวแปร CSS --fallback-progress
เป็นทางเลือกสำรองในการควบคุมไทม์ไลน์ภาพเคลื่อนไหวสำหรับพร็อพเพอร์ตี้ translate
และ opacity
จากนั้นระบบจะอัปเดตตัวแปร CSS --fallback-progress
ด้วยevent listener และ requestAnimationFrame
ใน JavaScript ดังนี้scroll
function updateProgress() {
const end = el.offsetTop + el.offsetHeight;
const start = end - window.innerHeight;
const scrollTop = document.scrollingElement.scrollTop;
const progress = (scrollTop - start) / (end - start);
document.body.style.setProperty('--fallback-progress', clamp(progress, 0, 1));
}
if (!CSS.supports("animation-timeline: view()")) {
document.addEventListener('scroll', () => {
if (!visible || updating) {
return;
}
window.requestAnimationFrame(() => {
updateProgress();
updating = false;
});
updating = true;
});
}
แหล่งข้อมูล
- กรณีศึกษาภาพเคลื่อนไหวที่ทำงานตามการเลื่อน
- เดโม: ภาพเคลื่อนไหวที่ทำงานตามการเลื่อน
- ทำให้องค์ประกอบเคลื่อนไหวเมื่อเลื่อนด้วยภาพเคลื่อนไหวที่ทำงานตามการเลื่อน
- Codelab: เริ่มต้นใช้งานภาพเคลื่อนไหวที่ทำงานตามการเลื่อนใน CSS
- ส่วนขยาย Chrome: โปรแกรมแก้ไขข้อบกพร่องภาพเคลื่อนไหวที่ทำงานโดยการเลื่อน
- Polyfill ไทม์ไลน์การเลื่อน
- รายงานข้อบกพร่องหรือฟีเจอร์ใหม่ เราอยากฟังความคิดเห็นจากคุณ
ขอขอบคุณเป็นพิเศษ Hannah Van Opstal, Bramus และ Andrew Kean Guan จาก Google และ Ingrid Reime จาก NRK ที่ให้ความร่วมมืออันมีค่าในงานนี้