文字動畫
關鍵字收斂
散落的關鍵字雲向中心收攏、彼此融合,最後收斂成一句結論的 React 文字動畫元件,適合把一堆零散想法歸納成核心訊息的段落。
把一堆零散想法歸納成一句核心訊息。關鍵字先以黃金角螺旋散布在整個區塊裡各自漂浮,觸發後由遠到近依序被彈簧拉向中心,途中縮小、模糊、淡出;接近中心時亮起一圈光暈,結論句再逐字從模糊中浮現,以 {{ }} 標記的詞用強調色顯示。可設定進入視窗自動播放、點擊觸發或完全受控,也能循環播放。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add keyword-convergePlayground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
800
90
編輯中的呼叫預設屬性
<KeywordConverge/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add https://webberui.com/r/keyword-converge.json或在 components.json 設定 registries 後,改用 @webberui/keyword-converge 安裝。
使用
import { KeywordConverge } from "@/components/ui/keyword-converge";
<KeywordConverge
keywords={[
{ text: "客訴變多", weight: 3 },
{ text: "回覆太慢", weight: 3 },
{ text: "資料分散", weight: 2 },
"人力不足",
"重複輸入",
"找不到紀錄",
]}
conclusion="問題不在人,在於{{資訊沒有集中}}"
trigger="inView"
delay={800}
/>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
keywords | (KeywordConvergeItem | string)[] | — | 關鍵字清單,可傳字串或物件(建議 8–20 個) |
conclusion | string | — | 收斂後浮現的結論句;以 {{ }} 包住的詞用強調色顯示 |
phase | "scatter" | "converge" | "resolved" | — | 受控的目前階段;未提供時由元件內部管理 |
defaultPhase | "scatter" | "converge" | "resolved" | "scatter" | 非受控模式的初始階段 |
onPhaseChange | (phase: KeywordConvergePhase) => void | — | 階段變動時回呼 |
trigger | "inView" | "click" | "manual" | "inView" | 觸發方式:進入視窗後延遲自動收斂、點擊容器、或只由 phase 驅動 |
delay | number | 800 | trigger="inView" 時進入視窗到開始收斂的延遲(毫秒) |
loop | boolean | false | 結論停留 holdDuration 後回到散布;搭配 inView 會自動再收斂 |
holdDuration | number | 3000 | 循環時結論停留的時間(毫秒) |
glow | boolean | true | 關鍵字接近中心時是否亮起光暈 |
stiffness | number | 90 | 飛行彈簧剛性,數值越大越急促 |
damping | number | 16 | 飛行彈簧阻尼,數值越大越不回彈 |
as | "p" | "h2" | "h3" | "h4" | "div" | "span" | "p" | 結論句的標籤 |
convergeHint | string | "點擊收斂" | trigger="click" 時散布狀態的提示文字 |
resetHint | string | "點擊重新散開" | trigger="click" 時結論狀態的提示文字 |
className | string | — | 透傳到最外層容器;預設 min-h-[320px],可在這裡覆寫高度 |
KeywordConvergeItem
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
id | string | 索引+文字 | 穩定識別碼 |
text | string | — | 關鍵字文字 |
weight | 1 | 2 | 3 | 2 | 視覺權重:決定字級(三級)與不透明度(0.5/0.75/1) |
CSS 變數
| 變數 | 預設值 | 說明 |
|---|---|---|
--wb-keyword-converge-stagger | 40ms | 關鍵字之間的出發間隔(由遠到近) |
--wb-keyword-converge-accent | #3b82f6 | 光暈與 {{ }} 強調詞的顏色 |
--wb-keyword-converge-glow | 600ms | 光暈擴張再收回的總時長 |
細節
- 散布位置是確定性的:黃金角螺旋加上依索引雜湊的小幅偏移,不使用
Math.random,伺服器與瀏覽器渲染結果一致,也不會每次重整都換位置;中央保留給結論句。 - 收斂順序依離中心的距離由遠到近,遠的先出發,最後幾乎同時抵達中心;反向飛散時近的先出發。
- 結論句以
Array.from逐字拆分,中日韓文字每個字獨立浮現(每字間隔 25ms),英文則以詞為群組,不會在單字中間斷行。 --wb-keyword-converge-stagger與--wb-keyword-converge-glow在掛載時讀取一次,用來排定光暈與結論出現的時間點。- 循環搭配
trigger="inView"時,回到散布後會多等約 1.2 秒才再次收斂,讓飛散的關鍵字先回到定位。
可及性
- 關鍵字層與逐字動畫都設定
aria-hidden;另有一段sr-only文字輸出「關鍵字:A、B、C。結論:……」,螢幕閱讀器一次取得完整內容 - 結論句容器為
aria-live="polite",只在進入 resolved 時填入文字,散布與收斂期間不會被朗讀 trigger="click"時整個區塊由一顆type="button"覆蓋,可用 Tab 聚焦、Enter/Space 觸發,帶focus-visible外框與可見的文字提示;收斂進行中按鈕暫時停用- 使用者系統開啟「減少動態效果」時,關鍵字不漂浮、不飛行,原地淡出後結論整句直接淡入,不做光暈與逐字模糊