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

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

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

สาธิต

หากต้องการดูวิดีโอ โปรดใช้โพสต์นี้ในเวอร์ชัน 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 เพื่อเปิดใช้ไวยากรณ์ของ 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 เพื่อให้ได้ผลลัพธ์ เราต้องใช้กล่อง ถ้าเราต้องการทำให้ตัวอักษรแต่ละตัวเคลื่อนไหว แต่ละตัวอักษรจะต้องเป็นองค์ประกอบ ถ้าเราต้องการทำให้แต่ละคำเคลื่อนไหว แต่ละคำ คำต้องเป็นองค์ประกอบ

  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 ที่แสดงให้เห็นแอตทริบิวต์ทั้งสอง

<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%);
      }
    }
  }
}

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

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