文字動畫
Handwriting Text
以 SVG pathLength 逐筆描繪的手寫文字動畫,內建單線字型,也支援自訂簽名路徑。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add "https://webberui.com/r/handwriting-text.json?t=<安裝 token>"Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
0.7
0.18
5
0
編輯中的呼叫預設屬性
<HandwritingText/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add "https://webberui.com/r/handwriting-text.json?t=<安裝 token>"或在 components.json 設定 registries 後,改用 @webberui/handwriting-text 安裝。
使用
傳入 text,會以內建單線字型逐筆描繪(文字自動轉為大寫):
import { HandwritingText } from "@/components/ui/handwriting-text";
<HandwritingText text="Webber" className="text-5xl font-medium" />若要描繪簽名或花體,改傳 paths(SVG 路徑 d 陣列)並搭配 viewBox:
<HandwritingText
paths={["M10 66 C 24 20 40 22 42 60 …", "M6 90 C 90 76 200 76 262 88"]}
viewBox="0 0 272 100"
label="手寫簽名"
/>節奏與手動觸發
totalDuration 指定整段描繪的總長,元件會把 duration 與 stagger 等比縮放,筆畫之間的相對快慢不變;easing 可傳 cubic-bezier() 字串、四元數組或 motion 具名緩動。trigger="manual" 時由 play 控制開始,搭配遞增 key 就能做出「重播」:
const [play, setPlay] = React.useState(false);
const [replayKey, setReplayKey] = React.useState(0);
<button type="button" onClick={() => setPlay(true)}>
<HandwritingText
key={replayKey}
text="Hello"
trigger="manual"
play={play}
totalDuration={2.8}
easing="cubic-bezier(0.2,0.2,0.8,0.9)"
delay={0.2}
onComplete={() => console.log("done")}
/>
</button>
<button type="button" onClick={() => setReplayKey((k) => k + 1)}>重播</button>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
text | string | — | 要描繪的文字,以內建單線字型渲染(自動轉大寫);與 paths 二擇一 |
paths | string[] | — | 自訂 SVG 路徑(d 字串陣列),提供時取代 text |
viewBox | string | "0 0 100 100" | paths 模式的 viewBox;text 模式會自動計算 |
label | string | — | paths 模式提供給輔助科技的文字說明 |
duration | number | 0.7 | 單一筆畫描繪時長(秒) |
stagger | number | 0.18 | 相鄰筆畫開始的間隔(秒) |
delay | number | 0 | 整體開始前的延遲(秒) |
easing | [number, number, number, number] | "cubic-bezier(…)" | "linear" | "easeIn" | "easeOut" | "easeInOut" | [0.22, 1, 0.36, 1] | 筆畫緩動;建議的手寫節奏為 "cubic-bezier(0.2,0.2,0.8,0.9)",字串無法解析時退回預設 |
totalDuration | number | — | 整段描繪的總時長(秒),依 duration/stagger 比例等比縮放;建議 2.8。不傳則各筆畫照 duration 計時 |
play | boolean | false | trigger 為 manual 時是否描繪;true 開始、false 收回 |
onComplete | () => void | — | 最後一筆畫描繪完成時呼叫;loop 時不觸發 |
strokeWidth | number | 5 | 線寬(viewBox 單位) |
fill | boolean | false | 描繪完成後淡入填色,適合封閉路徑;loop 時忽略 |
loop | boolean | false | 是否循環重繪 |
trigger | "view" | "hover" | "mount" | "manual" | "view" | 觸發時機;manual 由 play 控制 |
once | boolean | true | trigger 為 view 時,只在第一次進入視口播放 |
className | string | — | 外層容器;text 模式以 font-size 控制尺寸,paths 模式以寬度控制 |
svgClassName | string | — | 直接套用到 <svg>,可覆寫預設尺寸類別 |
細節
- 尺寸:
text模式的<svg>高度為1em,用text-5xl之類的字級類別即可縮放;paths模式寬度撐滿容器,用外層寬度控制大小。 - 顏色:描邊使用
currentColor,直接用text-neutral-*等文字色類別上色即可,深淺色主題各自設定。 - 單線字型:內建 A–Z、0–9 與常見標點,字母皆為大寫;每個字符拆成數筆畫並依書寫順序描繪。未收錄的字符會以空白間距處理。
- 循環:
loop開啟時各筆畫共用相同週期,重繪時仍保持原本的錯位順序,不會亂序閃動。 - 觸發:
trigger="hover"時容器可聚焦(tabIndex=0),滑鼠移入或鍵盤 focus 都會重新描繪。 - pathLength 標準化:每條路徑的
pathLength都被標準化為 1,虛線長度以 0–1 計算、與路徑實際長度無關,因此長短不一的筆畫能共用同一組時間參數。 - 總時長:
totalDuration只縮放時間,不改變筆畫順序與錯位比例;delay不計入總時長。
可及性
trigger="manual"不綁任何按鍵;要「按空白鍵開始」時,把元件放在原生<button>裡,空白鍵與 Enter 會由瀏覽器觸發 click。text模式下容器帶role="img"與aria-label,並保留一份sr-only文字供螢幕報讀。paths模式請透過label提供文字說明;未提供text也未提供label時,整體以aria-hidden對輔助科技隱藏。- 使用者系統開啟「減少動態效果」時,直接顯示描繪完成的靜態成品,不播放動畫。