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