การสร้างภาพเคลื่อนไหวแบบข้อความแบบแยก

ภาพรวมพื้นฐานเกี่ยวกับวิธีสร้างภาพเคลื่อนไหวของตัวอักษรและคำที่แยกออกจากกัน

ในโพสต์นี้ เราต้องการแชร์แนวคิดเกี่ยวกับวิธีแก้ปัญหาภาพเคลื่อนไหวและอินเทอร์แอกชันของข้อความแบบแยกส่วนสำหรับเว็บที่เรียบง่าย เข้าถึงได้ และใช้งานได้ในเบราว์เซอร์ต่างๆ ลองใช้เดโม

สาธิต

หากต้องการดูวิดีโอ โปรดดูโพสต์เวอร์ชัน YouTube ที่นี่

ภาพรวม

ภาพเคลื่อนไหวของการแยกข้อความก็น่าทึ่ง เราแทบจะไม่ได้เริ่มใช้งานภาพเคลื่อนไหวเลยในโพสต์นี้ แต่ข้อความนี้เป็นรากฐานในการต่อยอด เป้าหมายคือการสร้างภาพเคลื่อนไหวแบบเป็นขั้นเป็นตอน ข้อความควรอ่านออกได้โดยค่าเริ่มต้น โดยมีภาพเคลื่อนไหววางซ้อนอยู่ด้านบน เอฟเฟกต์การเคลื่อนไหวของข้อความแบบแยกอาจดูฟุ่มเฟือยและอาจรบกวนผู้ใช้ได้ ดังนั้นเราจะดัดแปลงเฉพาะ HTML หรือใช้สไตล์การเคลื่อนไหวในกรณีที่ผู้ใช้ยอมรับการเคลื่อนไหว

ภาพรวมทั่วไปของเวิร์กโฟลว์และผลลัพธ์มีดังนี้

  1. เตรียมตัวแปรแบบมีเงื่อนไขของการเคลื่อนไหวที่ลดลงสำหรับ CSS และ JS
  2. เตรียมยูทิลิตีข้อความแยกใน JavaScript
  3. จัดระเบียบเงื่อนไขและยูทิลิตีเมื่อโหลดหน้าเว็บ
  4. เขียนการเปลี่ยนและภาพเคลื่อนไหว CSS สำหรับตัวอักษรและคำ (ส่วนเจ๋งๆ)

ต่อไปนี้คือตัวอย่างผลลัพธ์แบบมีเงื่อนไขที่เราต้องการ

ภาพหน้าจอของเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ Chrome ที่เปิดแผง Elements อยู่และลดการเคลื่อนไหวที่ตั้งค่าเป็น "ลด" และ H1 แสดงไม่แยกส่วน
ผู้ใช้ต้องการลดการเคลื่อนไหว: ข้อความอ่านง่าย / ไม่แยก

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

ภาพหน้าจอของเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ Chrome ที่เปิดแผง Elements อยู่และลดการเคลื่อนไหวที่ตั้งค่าเป็น "ลด" และ H1 แสดงไม่แยกส่วน
ผู้ใช้เคลื่อนไหวได้ ข้อความแบ่งออกเป็นองค์ประกอบ <span> หลายองค์ประกอบ

การเตรียมเงื่อนไขการเคลื่อนไหว

ระบบจะใช้คิวรีสื่อ @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 ไม่ได้ เราต้องใช้กล่องเพื่อให้เกิดเอฟเฟกต์ หากต้องการให้แต่ละตัวอักษรเคลื่อนไหว ตัวอักษรแต่ละตัวจะต้องเป็นองค์ประกอบ หากต้องการให้แต่ละคำเคลื่อนไหว แต่ละคำจะต้องเป็นองค์ประกอบ

  1. สร้างฟังก์ชันยูทิลิตี JavaScript สำหรับการแยกสตริงออกเป็นองค์ประกอบ
  2. จัดการการใช้ยูทิลิตีเหล่านี้

ฟังก์ชันยูทิลิตีการแยกตัวอักษร

จุดเริ่มต้นที่น่าสนใจคือฟังก์ชันที่รับสตริงและแสดงผลตัวอักษรแต่ละตัวในอาร์เรย์

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()

การจัดการเป็นกลุ่มแบบแยก

เมื่อยูทิลิตีการแยกพร้อมใช้งานแล้ว การนำทุกอย่างมารวมกันจะมีลักษณะดังนี้

  1. การค้นหาองค์ประกอบที่จะแยก
  2. แยกและแทนที่ข้อความด้วย 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 ดังกล่าวอ่านเป็นภาษาอังกฤษได้ดังนี้

  1. นําเข้าฟังก์ชันยูทิลิตีตัวช่วยบางรายการ
  2. ตรวจสอบว่าผู้ใช้รายนี้สามารถใช้ฟีเจอร์การเคลื่อนไหวได้หรือไม่ หากไม่ ให้ดำเนินการใดๆ ทั้งสิ้น
  3. สําหรับองค์ประกอบแต่ละรายการที่ต้องการแยก
    1. แบ่งแคมเปญตามวิธีการที่ต้องการแบ่ง
    2. แทนที่ข้อความด้วยองค์ประกอบ

การแยกภาพเคลื่อนไหวและการเปลี่ยน

การจัดการเอกสารด้วยการแยกข้างต้นได้เปิดโอกาสให้ใช้ภาพเคลื่อนไหวและเอฟเฟกต์ได้มากมายด้วย 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;
}
เครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ Flexbox ที่แสดงช่องว่างระหว่างคำ

ตัวอย่างคำที่แบ่งช่วงทรานซิชัน

ในตัวอย่างนี้ เราจะใช้การโฮเวอร์อีกครั้ง เนื่องจากเอฟเฟกต์จะซ่อนเนื้อหาไว้จนกว่าจะมีการวางเมาส์เหนือ เราจึงตรวจสอบว่าใช้การโต้ตอบและสไตล์เฉพาะในกรณีที่อุปกรณ์สามารถวางเมาส์เหนือได้

@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