文字動畫

劃線改寫文字

劃線改寫文字 React 元件:句子先被一筆手繪劃線劃掉,再由新句子從下方升起取代,可串接多組,適合「舊說法 → 新說法」的論點翻轉與客訴翻轉成新功能的敘事。

把「舊說法」劃掉、換成「新說法」的文字動畫。每一組句子先完整顯示,接著一筆略帶手繪抖動的線從左到右劃過,舊句子淡出讓位,新句子帶著輕微模糊從下方彈性升起,並可選擇以底色由左到右刷入強調。多組句子會依序播放,適合落地頁的痛點翻轉、產品更新公告或簡報式的論點對比;也可以開啟 keepStruck,讓被劃掉的舊句子縮小留在上方當作刪除線註記。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add strike-reframe-text

還沒有專案,或安裝遇到問題?看快速開始 →

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

450
1600
編輯中的呼叫預設屬性
<StrikeReframeText/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

安裝

npx webberui@latest add https://webberui.com/r/strike-reframe-text.json

或在 components.json 設定 registries 後,改用 @webberui/strike-reframe-text 安裝。

使用

import { StrikeReframeText } from "@/components/ui/strike-reframe-text";

<StrikeReframeText
  as="h2"
  loop
  pairs={[
    { from: "整理報表要花一整個下午", to: "報表三分鐘自動產生" },
    { from: "每次對帳都要手動複製貼上", to: "對帳單自動彙整" },
  ]}
  className="text-3xl font-semibold"
/>

Props

Prop型別預設值說明
pairsStrikeReframePair[]—依序播放的句組;每組先劃掉 from,再由 to 升起取代
as"p" | "h2" | "span""p"根元素標籤;span 會以行內區塊呈現,可放進段落中
autoPlaybooleantrue一組播完後是否自動前進到下一組;關閉時只播目前這一組
trigger"mount" | "inView""inView"開始播放的時機:掛載即播,或捲進視窗才播(只觸發一次)
loopbooleanfalse最後一組播完後是否回到第一組
keepStruckbooleanfalse保留劃線態:舊句子縮小移到上方成為刪除線註記
highlightbooleantrue新句子升起後以底色由左到右刷入強調
strikeDurationnumber450劃線動畫時長(毫秒);未提供時讀取 --wb-strike-reframe-duration,再退回 450
holdBeforenumber900舊句子完整顯示、開始劃線前的停留時間(毫秒)
holdAfternumber1600新句子出現後、進入下一組前的停留時間(毫秒)
indexnumber—受控的目前組別索引;提供時由外部切換組別,元件只播動畫
defaultIndexnumber0非受控模式的初始組別索引
onIndexChange(index: number) => void—元件要前進到下一組時回呼;受控模式下由你決定是否採用
classNamestring—透傳到根元素,字級、字重、顏色都在這裡設定

StrikeReframePair

欄位型別預設值說明
fromstring—先出現、隨後被劃掉的舊句子
tostring—從下方升起、取代舊句子的新句子

細節

  • 每組的節奏:舊句子停留 holdBefore → 劃線 strikeDuration(緩動 [0.65, 0, 0.35, 1])→ 新句子以彈簧(stiffness 320、damping 28)從 18px 下方、4px 模糊升起 → 停留 holdAfter 後進入下一組。
  • 劃線依舊句子的實際排版量測(ResizeObserver+字型載入後重量),句子換行時每一行各畫一筆、依序劃過;線條的抖動由句子內容的雜湊決定,同一句話每次畫出的線都一樣,伺服器與瀏覽器輸出一致。
  • 外觀可用 CSS 變數覆寫:--wb-strike-reframe-line(線色,預設 #f43f5e)、--wb-strike-reframe-highlight(強調底色,預設 rgb(250 204 21 / 0.35))、--wb-strike-reframe-duration(劃線時長,預設 450ms)。
  • 新舊句子疊在同一格 grid 裡,容器寬高取兩者較大者,切換時版面不會跳動;keepStruck 時根元素會預留上方空間給縮小的刪除線註記。
  • 受控模式下,元件播完一組後只會呼叫 onIndexChange 提議下一組;你不更新 index 就會停在目前這組。

可及性

  • 動畫視覺層設為 aria-hidden;螢幕閱讀器讀到的是 sr-only 文字「原本:舊句子;現在:新句子」,語意完整不依賴動畫。
  • 另有 aria-live="polite" 區域,只在組別改變時宣告新句子;初次載入不宣告,避免重複朗讀。
  • 選擇 as="h2" 時標題的可及名稱同樣是完整的「原本/現在」句子,不會只讀到被劃掉的那一半。
  • 使用者系統開啟「減少動態效果」時不畫線、不位移:時間到直接以 150ms 淡切到新句子,舊句子以小字刪除線樣式保留在上方。