ภาพรวมพื้นฐานของวิธีสร้างภาพเคลื่อนไหวอักษรแยกและคำ
ในโพสต์นี้ เราอยากจะแชร์ความคิดเห็นเกี่ยวกับวิธีแก้โจทย์ภาพเคลื่อนไหวแบบแบ่งข้อความ และ การโต้ตอบสำหรับเว็บที่น้อยที่สุด เข้าถึงได้ และทำงานได้ในหลายเบราว์เซอร์ ทดลองใช้การสาธิต
หากต้องการดูวิดีโอ โปรดใช้โพสต์นี้ในเวอร์ชัน YouTube
ภาพรวม
ภาพเคลื่อนไหวของการแยกข้อความก็น่าทึ่ง เราแทบจะไม่มีรอยขีดข่วนของ ภาพเคลื่อนไหวในโพสต์นี้ แต่ก็เป็นพื้นฐานในการสร้าง ตาม โดยมีเป้าหมายเพื่อสร้างภาพเคลื่อนไหวอย่างต่อเนื่อง ข้อความควรสามารถอ่านได้ โดยมีภาพเคลื่อนไหวที่สร้างด้านบน เอฟเฟกต์การเคลื่อนไหวแบบแบ่งข้อความสามารถ ฟุ่มเฟือยและอาจรบกวนจิตใจ ดังนั้นเราจะแก้ไขเฉพาะ HTML หรือ ใช้รูปแบบการเคลื่อนไหวหากผู้ใช้พอใจกับการเคลื่อนไหว
ต่อไปนี้เป็นภาพรวมทั่วไปของขั้นตอนการทำงานและผลลัพธ์
- เตรียมภาพเคลื่อนไหวที่ลดลงแบบมีเงื่อนไข สำหรับ CSS และ JS
- เตรียมยูทิลิตีข้อความแบบแยกใน JavaScript
- เรียบเรียงเงื่อนไขและยูทิลิตีในหน้า โหลด
- เขียนการเปลี่ยนและภาพเคลื่อนไหว CSS สำหรับตัวอักษรและคำ (ส่วน rad!)
นี่คือตัวอย่างของผลการค้นหาแบบมีเงื่อนไขที่เราต้องการ
![ภาพหน้าจอของเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ Chrome ที่เปิดแผงองค์ประกอบและลดการเคลื่อนไหวเป็น "ลด" และ H1 แสดงแยกไม่ออก](https://web.dev/static/articles/building/split-text-animations/image/screenshot-the-chrome-de-65fd5b490f405.png?authuser=5&hl=th)
หากผู้ใช้ต้องการให้มีการเคลื่อนไหวน้อยลง เราจะปล่อยเอกสาร HTML ไว้ตามเดิมและไม่ ภาพเคลื่อนไหว หากภาพเคลื่อนไหวเหมาะสม เราจะตัดภาพนั้นแยกเป็นชิ้นๆ ต่อไปนี้คือ การแสดงตัวอย่าง HTML หลังจากที่ JavaScript แยกข้อความตามตัวอักษร
![ภาพหน้าจอของเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ Chrome ที่เปิดแผงองค์ประกอบและลดการเคลื่อนไหวเป็น "ลด" และ H1 แสดงแยกไม่ออก](https://web.dev/static/articles/building/split-text-animations/image/screenshot-the-chrome-de-fd950f1664ff6.png?authuser=5&hl=th)
กำลังเตรียมเงื่อนไขของการเคลื่อนไหว
ระบบจะใช้คิวรี่สื่อ @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
จาก
การฝังฉบับร่าง 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 ที่แสดงให้เห็นแอตทริบิวต์ทั้งสอง
<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%);
}
}
}
}
ตัวอย่างภาพเคลื่อนไหวแยกคำ
ในตัวอย่างภาพเคลื่อนไหวนี้ ฉันใช้ 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