文字動畫
劃線改寫文字
劃線改寫文字 React 元件:句子先被一筆手繪劃線劃掉,再由新句子從下方升起取代,可串接多組,適合「舊說法 → 新說法」的論點翻轉與客訴翻轉成新功能的敘事。
把「舊說法」劃掉、換成「新說法」的文字動畫。每一組句子先完整顯示,接著一筆略帶手繪抖動的線從左到右劃過,舊句子淡出讓位,新句子帶著輕微模糊從下方彈性升起,並可選擇以底色由左到右刷入強調。多組句子會依序播放,適合落地頁的痛點翻轉、產品更新公告或簡報式的論點對比;也可以開啟 keepStruck,讓被劃掉的舊句子縮小留在上方當作刪除線註記。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add strike-reframe-textPlayground
即時調整 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 | 型別 | 預設值 | 說明 |
|---|---|---|---|
pairs | StrikeReframePair[] | — | 依序播放的句組;每組先劃掉 from,再由 to 升起取代 |
as | "p" | "h2" | "span" | "p" | 根元素標籤;span 會以行內區塊呈現,可放進段落中 |
autoPlay | boolean | true | 一組播完後是否自動前進到下一組;關閉時只播目前這一組 |
trigger | "mount" | "inView" | "inView" | 開始播放的時機:掛載即播,或捲進視窗才播(只觸發一次) |
loop | boolean | false | 最後一組播完後是否回到第一組 |
keepStruck | boolean | false | 保留劃線態:舊句子縮小移到上方成為刪除線註記 |
highlight | boolean | true | 新句子升起後以底色由左到右刷入強調 |
strikeDuration | number | 450 | 劃線動畫時長(毫秒);未提供時讀取 --wb-strike-reframe-duration,再退回 450 |
holdBefore | number | 900 | 舊句子完整顯示、開始劃線前的停留時間(毫秒) |
holdAfter | number | 1600 | 新句子出現後、進入下一組前的停留時間(毫秒) |
index | number | — | 受控的目前組別索引;提供時由外部切換組別,元件只播動畫 |
defaultIndex | number | 0 | 非受控模式的初始組別索引 |
onIndexChange | (index: number) => void | — | 元件要前進到下一組時回呼;受控模式下由你決定是否採用 |
className | string | — | 透傳到根元素,字級、字重、顏色都在這裡設定 |
StrikeReframePair
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
from | string | — | 先出現、隨後被劃掉的舊句子 |
to | string | — | 從下方升起、取代舊句子的新句子 |
細節
- 每組的節奏:舊句子停留
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 淡切到新句子,舊句子以小字刪除線樣式保留在上方。