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

หากผู้ใช้ต้องการลดการเคลื่อนไหว เราจะไม่เปลี่ยนแปลงเอกสาร HTML และไม่ แสดงภาพเคลื่อนไหว หากการเคลื่อนไหวใช้ได้ เราจะตัดเป็นชิ้นๆ ต่อไปนี้คือ ตัวอย่าง HTML หลังจากที่ JavaScript แยกข้อความตามตัวอักษร

การเตรียมเงื่อนไขการเคลื่อนไหว
ระบบจะใช้ Media Query ที่พร้อมใช้งานอย่างสะดวกสบาย @media
(prefers-reduced-motion: reduce)
จาก CSS และ JavaScript ในโปรเจ็กต์นี้ Media Query นี้เป็นเงื่อนไขหลักของเราในการ
ตัดสินใจว่าจะแยกข้อความหรือไม่ ระบบจะใช้คำค้นหาสื่อ CSS เพื่อระงับการเปลี่ยนภาพและภาพเคลื่อนไหว ส่วนคำค้นหาสื่อ JavaScript จะใช้เพื่อระงับการจัดการ HTML
การเตรียม CSS แบบมีเงื่อนไข
ฉันใช้ PostCSS เพื่อเปิดใช้ไวยากรณ์ของ Media Queries ระดับ 5 ซึ่งฉันสามารถจัดเก็บ บูลีนของ Media Query ไว้ในตัวแปรได้
@custom-media --motionOK (prefers-reduced-motion: no-preference);
การเตรียม JS แบบมีเงื่อนไข
ใน JavaScript เบราว์เซอร์มีวิธีตรวจสอบ Media Query ซึ่งฉันใช้ การแยกโครงสร้าง เพื่อดึงและเปลี่ยนชื่อผลลัพธ์บูลีนจากการตรวจสอบ Media Query
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 มีลิงก์ 2-3 ลิงก์ที่ด้านล่างของบทความนี้เพื่อช่วยสร้างแรงบันดาลใจในการแยกเพลง
ถึงเวลาแสดงให้เห็นว่าคุณทำอะไรได้บ้างแล้ว ฉันจะแชร์ภาพเคลื่อนไหวและการเปลี่ยน 4 รายการที่ขับเคลื่อนด้วย CSS 🤓
ตัวอักษรแยก
ฉันพบว่า CSS ต่อไปนี้มีประโยชน์ในการเป็นพื้นฐานสำหรับเอฟเฟกต์ตัวอักษรแยก
ฉันใส่ทรานซิชันและภาพเคลื่อนไหวทั้งหมดไว้หลังการค้นหาสื่อการเคลื่อนไหว แล้ว
กำหนดพร็อพเพอร์ตี้การแสดงผลและสไตล์สำหรับสิ่งที่ต้องทำกับช่องว่างให้กับตัวอักษรย่อยใหม่แต่ละตัว span
[letter-animation] > span {
display: inline-block;
white-space: break-spaces;
}
รูปแบบช่องว่างมีความสำคัญเพื่อให้เครื่องมือจัดวางไม่ยุบช่วงที่มีเพียงช่องว่าง ตอนนี้มาดูเรื่องสนุกๆ ที่มีสถานะกัน
ตัวอย่างการเปลี่ยนตัวอักษรแยก
ตัวอย่างนี้ใช้การเปลี่ยน 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