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

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

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

การสาธิต

หากชอบวิดีโอ นี่คือโพสต์นี้เวอร์ชัน YouTube

ภาพรวม

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

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

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

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

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

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

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

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

ระบบจะใช้คิวรี่สื่อ @media (prefers-reduced-motion: reduce) ที่พร้อมใช้งานอย่างสะดวกจาก CSS และ JavaScript ในโปรเจ็กต์นี้ คิวรี่สื่อนี้เป็นเงื่อนไขหลักของเราในการตัดสินใจว่าจะแยกข้อความหรือไม่ ระบบจะใช้คิวรี่สื่อ CSS เพื่อระงับการเปลี่ยนและภาพเคลื่อนไหว ส่วนคิวรี่สื่อ JavaScript จะใช้เพื่อระงับการบิดเบือน HTML

กำลังเตรียม CSS แบบมีเงื่อนไข

ผมใช้ PostCSS เพื่อเปิดใช้ไวยากรณ์ของคำค้นหาสื่อระดับ 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)

ไวยากรณ์ที่แพร่หลายจาก 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 ได้ มีลิงก์อยู่ที่ด้านล่างของบทความนี้ซึ่งจะช่วยกระตุ้นศักยภาพของคุณในการแยกเนื้อหา

ถึงเวลาแสดงให้เห็นว่าคุณสามารถทำอะไรได้บ้าง ผมจะแชร์ภาพเคลื่อนไหวและการเปลี่ยน แบบที่ใช้ CSS 4 แบบ 🤓

แยกตัวอักษร

สำหรับพื้นฐานเกี่ยวกับเอฟเฟกต์แยกตัวอักษร ผมพบว่า CSS ต่อไปนี้มีประโยชน์มาก ฉันจะใส่การเปลี่ยนฉากและภาพเคลื่อนไหวทั้งหมดไว้ด้านหลังคำค้นหาสื่อการเคลื่อนไหว จากนั้นมอบพร็อพเพอร์ตี้การแสดงผลให้กับตัวอักษรย่อยใหม่ span แต่ละตัว รวมถึงสไตล์สำหรับทำอะไรกับการเว้นวรรค

[letter-animation] > span {
  display: inline-block;
  white-space: break-spaces;
}

รูปแบบช่องว่างมีความสำคัญเพื่อให้ Span ที่เป็นช่องว่างเท่านั้น ไม่ยุบโดยเครื่องมือเลย์เอาต์ พบกับเรื่องสนุกแบบเก็บสถานะแล้ว

ตัวอย่างตัวอักษรแยกส่วนการเปลี่ยน

ตัวอย่างนี้ใช้การเปลี่ยน 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%);
      }
    }
  }
}

ภาพเคลื่อนไหวตัวอย่างการแยกคำ

ในตัวอย่างภาพเคลื่อนไหวนี้ ฉันใช้ 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