文字動畫

Logo 進場動畫組

五種常見的 logo 進場:光暈放大、描邊後填色、掃光、圖標先到字標滑出、字標形變,可掛載、進入視口或手動觸發。

一個元件收齊五種品牌 logo 進場。bloom 從帶光的小亮點放大過衝再收斂;stroke 沿 SVG path 描線、再把淡描邊加深成最終色;shine 淡入後讓一道斜向高光只在 logo 筆畫內掃過;lockup 圖標先到、字標從圖標後方的遮罩滑出;morph 把字標逐字元形變成另一段文字,共用的字元會滑到新位置而不是重新出現。可選擇掛載時、進入視口時或以 ref.play() 手動播放,結束時呼叫 onComplete。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add logo-reveal-set

還沒有專案,或安裝遇到問題?看快速開始 →

Playground

即時調整 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型別預設值說明
childrenReactNode—圖標:SVG 或任意節點;有提供 path 時改由 path 繪製,children 不顯示
wordmarkReactNode—字標;morph 變體需為字串
morphTostring—morph 變體的目標字標,字標會從 wordmark 逐字形變成這段文字
pathstring—圖標的 SVG path(d 屬性);stroke 變體需要它才能描邊
viewBoxstring"0 0 64 64"path 的 SVG viewBox,需與 path 座標系一致
sizenumber48path 圖標的邊長(px)
strokeWidthnumber6path 的描邊粗細(viewBox 單位)
fillstring"none"path 的填色;none 時開放線條的「填色」階段改為描邊色加深
variant"bloom" | "stroke" | "shine" | "lockup" | "morph""bloom"進場變體
trigger"mount" | "inView" | "manual""mount"觸發時機;manual 時以 ref.play() 播放
durationnumber1.2進場總時長(秒);未指定時讀取 --wb-lrs-duration,再退回 1.2
glownumber0.6發光強度 0–1,映射到 0–16px 的兩層 drop-shadow
glowColorstring"var(--wb-lrs-glow, currentColor)"發光顏色
delaynumber0觸發後延遲多久開始(秒)
onComplete() => void—進場全部結束時呼叫;減少動態效果時於觸發當下立即呼叫
ariaLabelstringwordmark 文字外層 role="img" 的無障礙名稱
wordmarkClassNamestring—透傳到字標文字的 class(字級、字重等)
refRef<LogoRevealSetHandle>—命令式介面:play() 與 reset()
classNamestring—透傳到最外層容器

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(描邊階段的淡色)。傳了 duration prop 時以 prop 為準。
  • trigger 設為 inView 時以 IntersectionObserver 偵測,進入視口 35% 播放一次後停止觀察;任何模式都能用 ref.play() 重播。
  • 首次渲染(含伺服器端)都是進場前的隱藏狀態,與 client 一致,不會出現 hydration 差異。

可及性

  • 外層為 role="img",aria-label 預設取 wordmark 文字,可用 ariaLabel 覆寫;所有動畫層設 aria-hidden,形變中的逐字元不會被逐一朗讀
  • 動畫不會移動焦點,也不攔截鍵盤;重播按鈕由使用者自行提供,請用 type="button" 與清楚的文字
  • 使用者系統開啟「減少動態效果」時,所有變體直接顯示最終狀態(不做發光脈衝、morph 直接顯示目標文字),onComplete 於觸發當下立即呼叫