文字動畫
Logo 進場動畫組
五種常見的 logo 進場:光暈放大、描邊後填色、掃光、圖標先到字標滑出、字標形變,可掛載、進入視口或手動觸發。
一個元件收齊五種品牌 logo 進場。bloom 從帶光的小亮點放大過衝再收斂;stroke 沿 SVG path 描線、再把淡描邊加深成最終色;shine 淡入後讓一道斜向高光只在 logo 筆畫內掃過;lockup 圖標先到、字標從圖標後方的遮罩滑出;morph 把字標逐字元形變成另一段文字,共用的字元會滑到新位置而不是重新出現。可選擇掛載時、進入視口時或以 ref.play() 手動播放,結束時呼叫 onComplete。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add logo-reveal-setPlayground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
1.2
0.6
編輯中的呼叫預設屬性
<LogoRevealSet/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add https://webberui.com/r/logo-reveal-set.json或在 components.json 設定 registries 後,改用 @webberui/logo-reveal-set 安裝。
使用
import * as React from "react";
import {
LogoRevealSet,
type LogoRevealSetHandle,
} from "@/components/ui/logo-reveal-set";
const MARK = "M9.5 52C14 52 19 12 24 12C29 12 32 43 37 43C40.5 43 41.5 36 45 36L55 36";
export function Hero() {
const ref = React.useRef<LogoRevealSetHandle>(null);
return (
<>
<LogoRevealSet
ref={ref}
variant="stroke"
trigger="inView"
path={MARK}
strokeWidth={7.5}
wordmark="霧港設計"
onComplete={() => console.log("進場結束")}
/>
<button type="button" onClick={() => ref.current?.play()}>
重播
</button>
</>
);
}
// 圖標也可以是任意節點(不需描邊的變體)
<LogoRevealSet variant="lockup" wordmark="山嵐選品">
<svg width="40" height="40" viewBox="0 0 40 40" aria-hidden="true">
<circle cx="20" cy="20" r="16" fill="currentColor" />
</svg>
</LogoRevealSet>
// 字標形變
<LogoRevealSet variant="morph" wordmark="WebberUI" morphTo="Webber UI 元件庫" path={MARK} />Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | ReactNode | — | 圖標:SVG 或任意節點;有提供 path 時改由 path 繪製,children 不顯示 |
wordmark | ReactNode | — | 字標;morph 變體需為字串 |
morphTo | string | — | morph 變體的目標字標,字標會從 wordmark 逐字形變成這段文字 |
path | string | — | 圖標的 SVG path(d 屬性);stroke 變體需要它才能描邊 |
viewBox | string | "0 0 64 64" | path 的 SVG viewBox,需與 path 座標系一致 |
size | number | 48 | path 圖標的邊長(px) |
strokeWidth | number | 6 | path 的描邊粗細(viewBox 單位) |
fill | string | "none" | path 的填色;none 時開放線條的「填色」階段改為描邊色加深 |
variant | "bloom" | "stroke" | "shine" | "lockup" | "morph" | "bloom" | 進場變體 |
trigger | "mount" | "inView" | "manual" | "mount" | 觸發時機;manual 時以 ref.play() 播放 |
duration | number | 1.2 | 進場總時長(秒);未指定時讀取 --wb-lrs-duration,再退回 1.2 |
glow | number | 0.6 | 發光強度 0–1,映射到 0–16px 的兩層 drop-shadow |
glowColor | string | "var(--wb-lrs-glow, currentColor)" | 發光顏色 |
delay | number | 0 | 觸發後延遲多久開始(秒) |
onComplete | () => void | — | 進場全部結束時呼叫;減少動態效果時於觸發當下立即呼叫 |
ariaLabel | string | wordmark 文字 | 外層 role="img" 的無障礙名稱 |
wordmarkClassName | string | — | 透傳到字標文字的 class(字級、字重等) |
ref | Ref<LogoRevealSetHandle> | — | 命令式介面:play() 與 reset() |
className | string | — | 透傳到最外層容器 |
LogoRevealSetHandle
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
play | () => void | — | 從頭播放一次進場(任何 trigger 模式都可用,常用於「重播」) |
reset | () => void | — | 停止並回到進場前的隱藏狀態 |
細節
- 各變體都在
duration內分段:bloom前 45% 從 scale 0.05 放大到 1.15 並把發光推到最強,後 55% 收斂到 1、發光降到 glow×0.3;stroke前 70% 描邊、後 30% 加深上色;shine前 40% 淡入、後 60% 高光掃過;lockup前 40% 圖標 scale 0.8→1,之後字標以 spring(stiffness 220、damping 26)滑出;morph在 35% 時切換文字,新字元帶模糊淡入。 - 發光是兩層
drop-shadow(半徑 R 與 2R),會沿著圖形輪廓擴散,不會是方框陰影。 - 掃光的高光層是同一份內容的白色副本,以斜向
mask-image帶狀遮罩平移,所以高光只出現在筆畫內。若 children 是內含id(漸層、clipPath)的 SVG,副本會產生重複 id,建議改用path或不帶 id 的 SVG。 - 節奏與顏色可用 CSS 變數覆寫:
--wb-lrs-duration(時長,例如1.6s)、--wb-lrs-glow(發光色)、--wb-lrs-stroke(描邊階段的淡色)。傳了durationprop 時以 prop 為準。 trigger設為inView時以 IntersectionObserver 偵測,進入視口 35% 播放一次後停止觀察;任何模式都能用ref.play()重播。- 首次渲染(含伺服器端)都是進場前的隱藏狀態,與 client 一致,不會出現 hydration 差異。
可及性
- 外層為
role="img",aria-label預設取wordmark文字,可用ariaLabel覆寫;所有動畫層設aria-hidden,形變中的逐字元不會被逐一朗讀 - 動畫不會移動焦點,也不攔截鍵盤;重播按鈕由使用者自行提供,請用
type="button"與清楚的文字 - 使用者系統開啟「減少動態效果」時,所有變體直接顯示最終狀態(不做發光脈衝、
morph直接顯示目標文字),onComplete於觸發當下立即呼叫