建構分割文字動畫

瞭解如何建立分割字母和文字動畫的基礎總覽。

在這篇文章中,我想和大家分享如何解決分割文字動畫的問題。 透過各種瀏覽器使用網路,享受極少、存取和順暢的互動體驗。 歡迎查看示範內容

示範

如果您喜歡看影片,請參考這篇文章的 YouTube 版本:

總覽

分割文字動畫非常驚人我們會稍微抓到 但確實有助於建構 取代。目標是逐步加入動畫。文字 動畫預設是建立在最上面的動畫分割文字動態效果可以 過度雜亂且可能造成乾擾,因此我們只操縱 HTML 假如使用者動作符合情境,則套用動態樣式。

以下是工作流程和結果的概要說明:

  1. 準備減少動作條件 CSS 和 JS 的變數。
  2. 準備分割文字公用程式: JavaScript。
  3. 在網頁上自動化調度管理條件和公用程式 載入。
  4. 編寫 CSS 轉場效果和動畫 代表字母和字詞 (雷達部分!)。

以下為我們想要的條件式結果預覽:

Chrome 開發人員工具開啟「Elements」面板,並將動態效果設為「reduce」且 h1 顯示為未分割
使用者偏好減少動作:文字清晰易讀 / 未分割

如果使用者偏好減少動態效果,我們會單獨保留 HTML 文件,不做任何 如果動作沒有問題,我們就會將其切割成多個片段。請參考 JavaScript 將文字拆成一個字母,點選即可預覽 HTML 版本

Chrome 開發人員工具開啟「Elements」面板,並將動態效果設為「reduce」且 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 語法,檢查相同的值: 巢狀結構草稿 1。這樣一來 會儲存動畫的所有邏輯,以及動畫的樣式規定 。

letter-animation {
  @media (--motionOK) {
    /* animation styles */
  }
}

有了 PostCSS 自訂屬性和 JavaScript 布林值,我們就可以 有條件地升級效果這就說明瞭下一節 拆解用來將字串轉換為元素的 JavaScript。

分割文字

CSS 或 JS 不能分別使用文字字母、字詞和行等動畫。 為實現效果,我們需要有方塊。如果要為每個字母建立動畫 每個字母都必須是元素如果要為每個字詞產生動畫 都必須是元素

  1. 建立 JavaScript 公用程式函式,將字串分割成元素
  2. 調度管理這些公用程式的用法
,瞭解如何調查及移除這項存取權。

分割字母公用程式函式

有一個有趣的起點是函式,這個函式會使用函式擷取字串並傳回每個 陣列中的字母。

export const byLetter = text =>
  [...text].map(span)

分散 語法讓工作快速簡單

分割字詞公用程式函式

與分割字母類似,此函式會採用字串並傳回每個字詞 陣列。

export const byWord = text =>
  text.split(' ').map(span)

split()敬上 方法,以便我們指定要切入的字元。 我傳遞了空白處,表示每個字詞之間有所分割。

設計方塊實用性

效果需要每個字母組成方塊,而在函式中,我們可以看到 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。JavaScript 會使用 split-by 屬性來尋找 元素,並為字母或字詞建立方塊。屬性 系統會使用 CSS 中的 letter-animationword-animation 來指定元素 並套用變形和動畫

以下 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. 將文字替換為元素。

分割動畫和轉場效果

上述的分割文件操控功能 讓 可能呈現的動畫和效果以下介紹 ,瞭解如何拓展您的分潤。

現在就來展現你如何做到這一點吧!我會分享 4 種 CSS 驅動動畫 轉場效果🤓

分割字母

我認為下列 CSS 是分割字母效果的基礎 很有幫助。我在動作媒體查詢後面加上所有轉場效果和動畫 然後為每個新的子項字母 span 加上一個顯示屬性,再加上元素樣式 如何使用空格:

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

空白空格樣式十分重要,確保跨距只是空格 不要由版面配置引擎收合現在來談談有狀態的有趣內容。

轉換分割字母範例

這個範例使用 CSS 轉換為分割文字效果。有了轉場效果 而引擎所需的狀態,而我選擇了三種狀態: 懸停、將遊標懸停在句子上或將遊標懸停在字母上。

當使用者將滑鼠遊標懸停在句子 (又稱容器) 上時,我會縮減所有字詞 就是把他們推向別處接著,當使用者將滑鼠遊標懸停在 。

@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 或主持自己的示範,並透過 Twitter 推文給我,我會將它新增到 下方的社群重混作品部分。

來源

更多示範和靈感

社群重混作品