Text Morph
兩段文字間的平滑變形過渡——相同字元滑移到新位置,不同字元淡出淡入,支援自動輪播與受控切換。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
3
0.5
10
<TextMorph />
安裝
npx shadcn@latest add https://webberui.com/r/text-morph.json或在 components.json 設定 registries 後,改用 @webberui/text-morph 安裝。
安裝依賴後,從 registry JSON(/r/text-morph.json 的 files[0].content)複製 text-morph.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge使用
import { TextMorph } from "@/components/ui/text-morph";
// 自動輪播(預設每 3 秒)
<TextMorph
texts={["Build faster.", "Ship sooner."]}
className="text-4xl font-bold"
/>
// 受控模式:由外部狀態決定顯示哪一段
const [index, setIndex] = useState(0);
<TextMorph texts={plans} index={index} interval={0} />Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
texts | string[] | — | 要循環變形的文字清單(至少一項) |
index | number | — | 受控模式:目前顯示的文字索引(自動對長度取模) |
defaultIndex | number | 0 | 非受控模式的初始索引 |
onIndexChange | (index: number) => void | — | 索引即將變化時回呼(自動輪播與受控切換皆觸發) |
interval | number | 3 | 自動輪播間隔(秒);設為 0 停用 |
duration | number | 0.5 | 單次變形動畫時長(秒) |
y | number | 10 | 新舊字元進出場的垂直位移(px) |
blur | boolean | true | 進出場是否附帶模糊 |
caseSensitive | boolean | false | 字元比對是否區分大小寫;false 時 H 會滑移成 h |
pauseOnHover | boolean | true | 滑鼠懸停時暫停自動輪播 |
細節
- 字元比對:每個字素依「字元 + 第 n 次出現」產生穩定 key,新舊文字共有的字元由 Motion layout 動畫平滑滑移到新位置,其餘字元向上飄出、自下方進場,形成「變形」而非整段換頁的效果
- 字素切割:以
Intl.Segmenter切割 grapheme,emoji、旗幟、中文組合字不會被拆壞 - 受控/非受控雙模式:傳入
index即為受控;自動輪播在兩種模式下都會透過onIndexChange通知下一個索引,受控端可自行決定是否採納 - 計時器管理:輪播計時器在 unmount、hover 暫停與參數變更時皆正確清理,不會殘留
可及性
- 使用者系統開啟「減少動態效果」時,文字照常輪替但直接切換,不做變形動畫
- 動畫層對輔助科技隱藏(
aria-hidden),另以sr-only提供目前完整文字,朗讀時是完整句子而非零碎字元 - 預設
pauseOnHover讓使用者能停下輪播閱讀;若內容重要,建議搭配受控模式提供明確的切換控制