ภาพรวมพื้นฐานของวิธีสร้างภาพเคลื่อนไหวแบบแยกตัวอักษรและภาพเคลื่อนไหว
ในโพสต์นี้ ผมจะแชร์วิธีคิดวิธีแก้ปัญหาภาพเคลื่อนไหวข้อความแยกและการโต้ตอบ สำหรับเว็บที่ประหยัด เข้าถึงได้ และทำงานบนเบราว์เซอร์ต่างๆ ได้ ทดลองใช้การสาธิต
หากชอบวิดีโอ นี่คือโพสต์นี้เวอร์ชัน YouTube
ภาพรวม
ภาพเคลื่อนไหวที่แสดงการแยกข้อความเป็นองค์ประกอบที่น่าทึ่งมาก เราแทบจะไม่ผิวเผิน ศักยภาพของภาพเคลื่อนไหวในโพสต์นี้ แต่เป็นพื้นฐานที่ต่อยอดไปได้ เป้าหมายคือการสร้างภาพเคลื่อนไหวอย่างต่อเนื่อง ข้อความควรอ่านได้ง่ายโดยค่าเริ่มต้น โดยสร้างภาพเคลื่อนไหวอยู่ด้านบน เอฟเฟกต์การเคลื่อนไหวของข้อความแบบแยกอาจซับซ้อนและอาจรบกวนผู้ใช้ เราจึงจะจัดการกับ HTML เท่านั้นหรือใช้รูปแบบการเคลื่อนไหวหากผู้ใช้ไม่รู้สึกดีเมื่อเคลื่อนไหว
ต่อไปนี้คือภาพรวมทั่วไปของเวิร์กโฟลว์และผลลัพธ์
- เตรียมตัวแปรเงื่อนไขของการเคลื่อนไหวที่ลดลง สำหรับ CSS และ JS
- เตรียมยูทิลิตีข้อความในการแยกข้อความใน JavaScript
- จัดระเบียบเงื่อนไขและยูทิลิตีในการโหลดหน้าเว็บ
- เขียนการเปลี่ยนและภาพเคลื่อนไหว CSS สำหรับตัวอักษรและคำ (ส่วน Rad!)
ต่อไปนี้คือตัวอย่างของผลลัพธ์แบบมีเงื่อนไขที่เราจะนำเสนอ:
หากผู้ใช้ต้องการลดการเคลื่อนไหว เราจะปล่อยเอกสาร HTML ไว้ตามเดิมและจะไม่สร้างภาพเคลื่อนไหว หากการเคลื่อนไหวเป็นปกติ เราจะแยกส่วนเป็นส่วนๆ นี่เป็นตัวอย่างของ HTML หลังจากที่ JavaScript แยกข้อความตามตัวอักษร
กำลังเตรียมเงื่อนไขของการเคลื่อนไหว
ระบบจะใช้คิวรี่สื่อ @media
(prefers-reduced-motion: reduce)
ที่พร้อมใช้งานอย่างสะดวกจาก CSS และ JavaScript ในโปรเจ็กต์นี้ คิวรี่สื่อนี้เป็นเงื่อนไขหลักของเราในการตัดสินใจว่าจะแยกข้อความหรือไม่ ระบบจะใช้คิวรี่สื่อ CSS เพื่อระงับการเปลี่ยนและภาพเคลื่อนไหว ส่วนคิวรี่สื่อ JavaScript จะใช้เพื่อระงับการบิดเบือน HTML
กำลังเตรียม CSS แบบมีเงื่อนไข
ผมใช้ PostCSS เพื่อเปิดใช้ไวยากรณ์ของคำค้นหาสื่อระดับ 5 ซึ่งผมสามารถจัดเก็บบูลีนคำค้นหาสื่อลงในตัวแปรได้
@custom-media --motionOK (prefers-reduced-motion: no-preference);
กำลังเตรียม JS แบบมีเงื่อนไข
ใน JavaScript เบราว์เซอร์มีวิธีตรวจสอบคำค้นหาสื่อ ผมใช้การทำลายเพื่อดึงข้อมูลและเปลี่ยนชื่อผลลัพธ์บูลีนจากการตรวจสอบคำค้นหาสื่อ ดังนี้
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
จากนั้นเราจะสามารถทดสอบ motionOK
และเปลี่ยนเอกสารเฉพาะในกรณีที่ผู้ใช้ไม่ได้ขอให้ลดการเคลื่อนไหว
if (motionOK) {
// document split manipulations
}
ผมตรวจสอบค่าเดียวกันนี้ได้โดยใช้ PostCSS เพื่อเปิดใช้ไวยากรณ์ @nest
จากNesting Draft 1 ซึ่งทำให้ผมเก็บตรรกะทั้งหมดเกี่ยวกับภาพเคลื่อนไหวและข้อกำหนดด้านรูปแบบของผู้ปกครองและเด็กไว้ได้ในที่เดียว
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
ด้วยพร็อพเพอร์ตี้ที่กำหนดเอง PostCSS และบูลีน JavaScript เราพร้อมที่จะอัปเกรดเอฟเฟกต์อย่างมีเงื่อนไข ซึ่งจะพาเราไปยังส่วนถัดไป คืออธิบาย JavaScript สำหรับการแปลงสตริงเป็นองค์ประกอบ
การแยกข้อความ
ตัวอักษร คำ บรรทัด ฯลฯ ต้องไม่เคลื่อนไหวแยกกันด้วย CSS หรือ JS เราจำเป็นต้องมีช่องเพื่อสร้างผลลัพธ์ หากต้องการทำให้ตัวอักษรแต่ละตัวเคลื่อนไหวได้ ตัวอักษรแต่ละตัวต้องเป็นองค์ประกอบ หากต้องการให้แต่ละคำเคลื่อนไหว คำแต่ละคำจะต้องเป็นองค์ประกอบหนึ่ง
- สร้างฟังก์ชันยูทิลิตี JavaScript สำหรับการแยกสตริงเป็นองค์ประกอบ
- จัดการการใช้งานยูทิลิตีเหล่านี้
ฟังก์ชันยูทิลิตีการแยกตัวอักษร
จุดเริ่มต้นสนุกๆ คือใช้ฟังก์ชันที่ใช้สตริงและส่งตัวอักษรแต่ละตัวกลับมาในอาร์เรย์
export const byLetter = text =>
[...text].map(span)
ไวยากรณ์ที่แพร่หลายจาก ES6 ช่วยให้ทำงานได้อย่างรวดเร็วจริงๆ
ฟังก์ชันยูทิลิตีการแยกคำ
ฟังก์ชันนี้จะใช้สตริงและแสดงผลแต่ละคำในอาร์เรย์ เช่นเดียวกับการแยกตัวอักษร
export const byWord = text =>
text.split(' ').map(span)
เมธอด split()
ในสตริง JavaScript ช่วยให้เราระบุอักขระที่จะแบ่งส่วนได้
ฉันข้ามช่องว่าง แสดงถึงการแยกคำระหว่างคำ
การสร้างฟังก์ชันยูทิลิตีกล่อง
เอฟเฟกต์ต้องมีช่องสำหรับตัวอักษรแต่ละตัว ซึ่งในฟังก์ชันเหล่านั้นจะมีการเรียก map()
ด้วยฟังก์ชัน span()
นี่คือฟังก์ชัน span()
const span = (text, index) => {
const node = document.createElement('span')
node.textContent = text
node.style.setProperty('--index', index)
return node
}
สิ่งสำคัญที่ควรทราบก็คือ มีการตั้งค่าพร็อพเพอร์ตี้ที่กำหนดเองชื่อ --index
ด้วยตำแหน่งอาร์เรย์ การมีช่องสำหรับใช้ภาพเคลื่อนไหวแบบตัวอักษรนั้นยอดเยี่ยมมาก
แต่การมีดัชนีเพื่อใช้ใน CSS เป็นเพียงส่วนเติมเต็มที่ดูเหมือนว่าจะเล็กน้อยแต่ให้ผลยิ่งใหญ่
สิ่งที่โดดเด่นที่สุดเกี่ยวกับผลกระทบใหญ่ๆ นี้ก็คือการใช้งานแบบส่าย
เราจะสามารถใช้ --index
ในการออฟเซ็ตภาพเคลื่อนไหวเพื่อให้ภาพสับเปลี่ยนไปได้
บทสรุปด้านสาธารณูปโภค
โมดูล splitting.js
เสร็จสมบูรณ์:
const span = (text, index) => {
const node = document.createElement('span')
node.textContent = text
node.style.setProperty('--index', index)
return node
}
export const byLetter = text =>
[...text].map(span)
export const byWord = text =>
text.split(' ').map(span)
ขั้นตอนถัดไปคือการนำเข้าและใช้ฟังก์ชัน byLetter()
และ byWord()
เหล่านี้
การแยกการจัดการเป็นกลุ่ม
เมื่อยูทิลิตีการแยกพร้อมใช้งานแล้ว การนำทุกอย่างมารวมกันจะมีความหมายดังนี้
- การค้นหาองค์ประกอบที่จะแยก
- การแยกและแทนที่ข้อความด้วย HTML
หลังจากนั้น CSS จะเข้ามาควบคุมและทำให้องค์ประกอบ / กล่องเคลื่อนไหว
การค้นหาองค์ประกอบ
ผมเลือกที่จะใช้แอตทริบิวต์และค่าต่างๆ เพื่อเก็บข้อมูล
เกี่ยวกับภาพเคลื่อนไหวที่ต้องการและวิธีแบ่งข้อความ ฉันชอบใส่ตัวเลือกเชิงประกาศเหล่านี้
ลงใน HTML แอตทริบิวต์ split-by
จะใช้จาก JavaScript เพื่อค้นหาองค์ประกอบและสร้างช่องสำหรับตัวอักษรหรือคำ แอตทริบิวต์ letter-animation
หรือ word-animation
จะใช้จาก CSS เพื่อกำหนดเป้าหมายองค์ประกอบย่อย และใช้การเปลี่ยนรูปแบบและภาพเคลื่อนไหว
ตัวอย่างของ HTML ที่แสดงให้เห็นแอตทริบิวต์ 2 แบบมีดังนี้
<h1 split-by="letter" letter-animation="breath">animated letters</h1>
<h1 split-by="word" word-animation="trampoline">hover the words</h1>
การค้นหาองค์ประกอบจาก JavaScript
ผมใช้ไวยากรณ์ตัวเลือก CSS สำหรับการแสดงแอตทริบิวต์เพื่อรวบรวมรายการองค์ประกอบที่ต้องการแยกข้อความ
const splitTargets = document.querySelectorAll('[split-by]')
การค้นหาองค์ประกอบจาก CSS
ฉันยังใช้ตัวเลือกการแสดงแอตทริบิวต์ใน CSS เพื่อให้ภาพเคลื่อนไหวตัวอักษรทั้งหมด มีรูปแบบพื้นฐานเหมือนกัน หลังจากนั้น เราจะใช้ค่าแอตทริบิวต์ในการเพิ่มสไตล์ที่เจาะจงมากขึ้นเพื่อให้ได้ผลลัพธ์
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
แยกข้อความตรงตำแหน่ง
สำหรับเป้าหมายการแยกแต่ละรายการที่พบใน JavaScript เราจะแยกข้อความตามค่าของแอตทริบิวต์และแมปแต่ละสตริงกับ <span>
จากนั้นเราสามารถแทนที่ข้อความขององค์ประกอบด้วยช่องที่เราสร้างขึ้น ดังนี้
splitTargets.forEach(node => {
const type = node.getAttribute('split-by')
let nodes = null
if (type === 'letter') {
nodes = byLetter(node.innerText)
}
else if (type === 'word') {
nodes = byWord(node.innerText)
}
if (nodes) {
node.firstChild.replaceWith(...nodes)
}
})
บทสรุปของการจัดการเป็นกลุ่ม
index.js
เสร็จสมบูรณ์:
import {byLetter, byWord} from './splitting.js'
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
if (motionOK) {
const splitTargets = document.querySelectorAll('[split-by]')
splitTargets.forEach(node => {
const type = node.getAttribute('split-by')
let nodes = null
if (type === 'letter')
nodes = byLetter(node.innerText)
else if (type === 'word')
nodes = byWord(node.innerText)
if (nodes)
node.firstChild.replaceWith(...nodes)
})
}
JavaScript สามารถอ่านเป็นภาษาอังกฤษต่อไปนี้ได้
- นำเข้าฟังก์ชันยูทิลิตีของตัวช่วยบางรายการ
- ตรวจสอบว่าการเคลื่อนไหวเหมาะสมสำหรับผู้ใช้รายนี้หรือไม่ หากไม่มีการดำเนินการ
- สำหรับแต่ละองค์ประกอบที่ต้องการแยก
- แบ่งกลุ่มตามวิธีที่ต้องการแยก
- แทนที่ข้อความด้วยองค์ประกอบ
การแยกภาพเคลื่อนไหวและการเปลี่ยนภาพ
การแยกการจัดการเอกสารข้างต้นได้ปลดล็อกภาพเคลื่อนไหวและเอฟเฟกต์ต่างๆ มากมายที่ใช้ CSS หรือ JavaScript ได้ มีลิงก์อยู่ที่ด้านล่างของบทความนี้ซึ่งจะช่วยกระตุ้นศักยภาพของคุณในการแยกเนื้อหา
ถึงเวลาแสดงให้เห็นว่าคุณสามารถทำอะไรได้บ้าง ผมจะแชร์ภาพเคลื่อนไหวและการเปลี่ยน แบบที่ใช้ CSS 4 แบบ 🤓
แยกตัวอักษร
สำหรับพื้นฐานเกี่ยวกับเอฟเฟกต์แยกตัวอักษร ผมพบว่า CSS ต่อไปนี้มีประโยชน์มาก ฉันจะใส่การเปลี่ยนฉากและภาพเคลื่อนไหวทั้งหมดไว้ด้านหลังคำค้นหาสื่อการเคลื่อนไหว จากนั้นมอบพร็อพเพอร์ตี้การแสดงผลให้กับตัวอักษรย่อยใหม่ span
แต่ละตัว รวมถึงสไตล์สำหรับทำอะไรกับการเว้นวรรค
[letter-animation] > span {
display: inline-block;
white-space: break-spaces;
}
รูปแบบช่องว่างมีความสำคัญเพื่อให้ Span ที่เป็นช่องว่างเท่านั้น ไม่ยุบโดยเครื่องมือเลย์เอาต์ พบกับเรื่องสนุกแบบเก็บสถานะแล้ว
ตัวอย่างตัวอักษรแยกส่วนการเปลี่ยน
ตัวอย่างนี้ใช้การเปลี่ยน CSS ไปยังเอฟเฟกต์ข้อความแบบแยก สำหรับการเปลี่ยน เราจำเป็นต้องมีสถานะเพื่อให้เครื่องมือเคลื่อนไหวไปมา และผมเลือก 3 สถานะคือ ไม่เลื่อนเคอร์เซอร์ วางเมาส์เหนือประโยค วางเมาส์เหนือตัวอักษร
เมื่อผู้ใช้วางเมาส์เหนือประโยค หรือที่เรียกว่าคอนเทนเนอร์ ฉันจะปรับขนาดตัวเด็กทั้งหมดกลับมาเหมือนกับว่าผู้ใช้ผลักเด็กออกห่างออกไป จากนั้นเมื่อผู้ใช้วางเมาส์เหนือจดหมาย ผมจะนำข้อความดังกล่าวไปข้างหน้า
@media (--motionOK) {
[letter-animation="hover"] {
&:hover > span {
transform: scale(.75);
}
& > span {
transition: transform .3s ease;
cursor: pointer;
&:hover {
transform: scale(1.25);
}
}
}
}
ภาพเคลื่อนไหวตัวอย่างการแยกตัวอักษร
ตัวอย่างนี้ใช้ภาพเคลื่อนไหว @keyframe
ที่กำหนดไว้ล่วงหน้าเพื่อทำให้ตัวอักษรแต่ละตัวเคลื่อนไหวได้ไม่รู้จบ และใช้ประโยชน์จากดัชนีพร็อพเพอร์ตี้ที่กำหนดเองแบบในหน้าเพื่อสร้างเอฟเฟกต์การสับเปลี่ยน
@media (--motionOK) {
[letter-animation="breath"] > span {
animation:
breath 1200ms ease
calc(var(--index) * 100 * 1ms)
infinite alternate;
}
}
@keyframes breath {
from {
animation-timing-function: ease-out;
}
to {
transform: translateY(-5px) scale(1.25);
text-shadow: 0 0 25px var(--glow-color);
animation-timing-function: ease-in-out;
}
}
แยกคำ
Flexbox ทำงานเป็นประเภทคอนเทนเนอร์สำหรับผมในตัวอย่างเหล่านี้ โดยใช้ประโยชน์จากหน่วย ch
ได้เป็นอย่างดี
word-animation {
display: inline-flex;
flex-wrap: wrap;
gap: 1ch;
}
ตัวอย่างการเปลี่ยนคำ
ในตัวอย่างการเปลี่ยนนี้ ผมใช้การวางเมาส์เหนืออีกครั้ง เนื่องจากเอฟเฟกต์จะซ่อนเนื้อหาไว้จนกว่าจะวางเมาส์ไว้ด้านบน ผมจึงยืนยันว่าระบบจะใช้การโต้ตอบและสไตล์เฉพาะเมื่ออุปกรณ์สามารถวางเมาส์ได้เท่านั้น
@media (hover) {
[word-animation="hover"] {
overflow: hidden;
overflow: clip;
& > span {
transition: transform .3s ease;
cursor: pointer;
&:not(:hover) {
transform: translateY(50%);
}
}
}
}
ภาพเคลื่อนไหวตัวอย่างการแยกคำ
ในตัวอย่างภาพเคลื่อนไหวนี้ ฉันใช้ CSS @keyframes
อีกครั้งเพื่อสร้างภาพเคลื่อนไหวที่ขยายไม่สิ้นสุดในย่อหน้าปกติของข้อความ
[word-animation="trampoline"] > span {
display: inline-block;
transform: translateY(100%);
animation:
trampoline 3s ease
calc(var(--index) * 150 * 1ms)
infinite alternate;
}
@keyframes trampoline {
0% {
transform: translateY(100%);
animation-timing-function: ease-out;
}
50% {
transform: translateY(0);
animation-timing-function: ease-in;
}
}
บทสรุป
ตอนนี้คุณก็รู้แล้วว่าผมทำยังไงแล้วคุณล่ะ คุณจะต้องทำอย่างไร 🙂
มาลองเปลี่ยนแนวทางของเราและเรียนรู้วิธีทั้งหมดเพื่อสร้างเว็บกันเถอะ สร้าง Codepen หรือโฮสต์เดโมของคุณเอง ทวีตฉันพร้อมใส่วิดีโอไว้ แล้วฉันจะเพิ่มลงในส่วนรีมิกซ์ของชุมชนด้านล่างนี้
แหล่งที่มา
การสาธิตและแรงบันดาลใจเพิ่มเติม
รีมิกซ์ของชุมชน
- คอมโพเนนต์เว็บ
<text-hover>
โดย gnehcwu ใน CodeSandbox