ภาพรวมพื้นฐานเกี่ยวกับวิธีสร้างภาพเคลื่อนไหวของตัวอักษรและคำที่แยกออกจากกัน
ในโพสต์นี้ เราต้องการแชร์แนวคิดเกี่ยวกับวิธีแก้ปัญหาภาพเคลื่อนไหวและอินเทอร์แอกชันของข้อความแบบแยกส่วนสำหรับเว็บที่เรียบง่าย เข้าถึงได้ และใช้งานได้ในเบราว์เซอร์ต่างๆ ลองใช้เดโม
หากต้องการดูวิดีโอ โปรดดูโพสต์เวอร์ชัน YouTube ที่นี่
ภาพรวม
ภาพเคลื่อนไหวของข้อความที่แยกออกมาอาจดูน่าทึ่ง โพสต์นี้เป็นเพียงข้อมูลเบื้องต้นเกี่ยวกับศักยภาพของภาพเคลื่อนไหว แต่จะเป็นรากฐานที่จะช่วยคุณต่อยอดได้ เป้าหมายคือการสร้างภาพเคลื่อนไหวแบบเป็นขั้นเป็นตอน ข้อความควรอ่านได้โดยค่าเริ่มต้น โดยมีภาพเคลื่อนไหววางอยู่ด้านบน เอฟเฟกต์การเคลื่อนไหวของข้อความแบบแยกอาจดูฟุ่มเฟือยและอาจรบกวนผู้ใช้ได้ ดังนั้นเราจะจัดการเฉพาะ HTML หรือใช้สไตล์การเคลื่อนไหวในกรณีที่ผู้ใช้ยอมรับการเคลื่อนไหว
ภาพรวมทั่วไปของเวิร์กโฟลว์และผลลัพธ์มีดังนี้
- เตรียมตัวแปรแบบมีเงื่อนไขของการเคลื่อนไหวที่ลดลงสำหรับ CSS และ JS
- เตรียมยูทิลิตีการแยกข้อความใน JavaScript
- จัดระเบียบเงื่อนไขและยูทิลิตีเมื่อโหลดหน้าเว็บ
- เขียนการเปลี่ยนและภาพเคลื่อนไหว CSS สำหรับตัวอักษรและคำ (ส่วนเจ๋งๆ)
ต่อไปนี้คือตัวอย่างผลลัพธ์แบบมีเงื่อนไขที่เราต้องการ
หากผู้ใช้ต้องการลดการเคลื่อนไหว เราจะไม่เปลี่ยนแปลงเอกสาร HTML และไม่ใส่ภาพเคลื่อนไหว หากการเคลื่อนไหวเรียบร้อยดี เราจะตัดวิดีโอออกเป็นส่วนๆ ต่อไปนี้คือตัวอย่าง HTML หลังจากที่ JavaScript แยกข้อความตามตัวอักษร
การเตรียมเงื่อนไขการเคลื่อนไหว
ระบบจะใช้คิวรีสื่อ @media
(prefers-reduced-motion: reduce)
ที่พร้อมใช้งานจาก CSS และ JavaScript ในโปรเจ็กต์นี้ การค้นหาสื่อนี้เป็นเงื่อนไขหลักในการตัดสินว่าจะแยกข้อความหรือไม่ ระบบจะใช้คำค้นหาสื่อ CSS เพื่อระงับการเปลี่ยนภาพและภาพเคลื่อนไหว ส่วนคำค้นหาสื่อ JavaScript จะใช้เพื่อระงับการจัดการ HTML
เตรียมเงื่อนไข CSS
ฉันใช้ PostCSS เพื่อเปิดใช้ไวยากรณ์ของ Media Queries ระดับ 5 ซึ่งฉันสามารถจัดเก็บบูลีน Media Query ไว้ในตัวแปรได้ ดังนี้
@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)
รูปแบบคำสั่ง spread จาก 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 ลิงก์ที่จะช่วยสร้างแรงบันดาลใจให้คุณแบ่งรายได้
มาดูกันว่าคุณจะทำอะไรได้บ้าง เราจะแชร์ภาพเคลื่อนไหวและการเปลี่ยน CSS 4 แบบ 🤓
แยกตัวอักษร
เราพบว่า 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%);
}
}
}
}
ตัวอย่างคำที่แยกออกเป็น 2 พยางค์
ในตัวอย่างภาพเคลื่อนไหวนี้ เราใช้ 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