動態字體排印
發表字幕序列
產品發表式的連續字幕卡:每張不同進場(模糊進、逐字、大字重擊、超大平移、漸層關鍵字),卡間背景翻轉,附 HUD 角標,可自動播放或隨捲動切換。
產品發表影片那種一張接一張的字幕卡,直接做成 React 元件。每張卡可以選五種進場——整行模糊收焦、逐詞錯開浮現、全大寫重擊後微震、超大字在停留期間緩慢橫移、關鍵字套漸層並掃過一次;卡與卡之間背景交叉淡接,或硬切成另一個顏色製造「色彩翻轉」。autoplay 模式在固定舞台裡依時間播放,離開畫面自動暫停;scroll 模式讓每張卡佔一個區段,捲到哪張就播哪張。四角的 HUD(編號、閃爍點、時間碼、L 形框線)可以關掉。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add "https://webberui.com/r/launch-title-sequence.json?t=<安裝 token>"Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
2200
編輯中的呼叫預設屬性
<LaunchTitleSequence/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add "https://webberui.com/r/launch-title-sequence.json?t=<安裝 token>"或在 components.json 設定 registries 後,改用 @webberui/launch-title-sequence 安裝。
使用
import {
LaunchTitleSequence,
type LaunchTitleCard,
} from "@/components/ui/launch-title-sequence";
const cards: LaunchTitleCard[] = [
{ eyebrow: "全新推出", headline: "拾光筆記", entrance: "punch", bg: "#0a0a0a", fg: "#fafafa" },
{ headline: "寫下的,**都找得到**。", entrance: "gradient", bg: "#ffffff", fg: "#171717" },
{ headline: "離線也能同步,跨裝置即時更新。", entrance: "words", bg: "#262626", fg: "#f5f5f5" },
{ headline: "今天就開始", sub: "免費下載", entrance: "pan", bg: "#2563eb", fg: "#ffffff", transition: "cut" },
];
// 自動播放(固定 16:9 舞台)
<LaunchTitleSequence cards={cards} className="rounded-xl" />
// 隨頁面捲動切換(每張卡佔一個 100vh 區段)
<LaunchTitleSequence cards={cards} mode="scroll" />Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
cards | LaunchTitleCard[] | — | 依序播放的字幕卡 |
mode | "autoplay" | "scroll" | "autoplay" | autoplay:固定舞台依時間播放;scroll:每張卡佔一個區段,隨捲動切換 |
transition | "crossfade" | "cut" | "crossfade" | 卡間背景轉場:crossfade 交叉淡接、cut 硬切 |
hold | number | 2200 | 每張卡預設停留毫秒數;未提供時讀 --wb-kts-hold,再退回 2200 |
loop | boolean | true | autoplay 播完最後一張是否回到第一張 |
paused | boolean | false | 外部暫停 autoplay(與內建暫停鈕並存,任一暫停即暫停) |
hud | boolean | true | 是否顯示 HUD 角標(編號、閃爍點、時間碼、四角框線) |
height | number | string | — | autoplay 為舞台高度(未提供時 16:9);scroll 為每張卡的區段高度(未提供時 100vh) |
scrollContainer | RefObject<HTMLElement | null> | — | scroll 模式的捲動容器;未提供時跟隨頁面捲動 |
index | number | — | 受控的目前卡片索引(僅 autoplay 有效;scroll 模式由捲動位置決定) |
defaultIndex | number | 0 | 非受控模式的初始卡片索引 |
onCardChange | (index: number) => void | — | 目前卡片改變時回呼,參數為新索引 |
className | string | — | 透傳到最外層容器 |
LaunchTitleCard
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
eyebrow | string | — | 標題上方的小字(例如「全新推出」),以寬字距淡入 |
headline | string | — | 主標題;gradient 進場時以 **雙星號** 包住的關鍵字會套漸層 |
sub | string | — | 主標題下方的副標,於主標題進場後 200ms 淡入 |
entrance | "blur" | "words" | "punch" | "pan" | "gradient" | — | 主標題的進場方式 |
bg | string | — | 卡片背景(任意 CSS 色或漸層);未提供時用 neutral 底色並跟隨深色模式 |
fg | string | — | 卡片文字色;有自訂 bg 時建議一併提供 |
hold | number | — | 此卡停留毫秒數,覆寫整體 hold |
transition | "crossfade" | "cut" | — | 進入此卡時的背景轉場,覆寫整體 transition |
細節
- 五種進場:
blur整行blur(16px)收焦、透明度與 8px 位移一起歸零;words依詞錯開浮現(英文以空白切,中文用Intl.Segmenter切詞,不支援時逐字,標點併入前一詞);punch全大寫、從 1.3 倍彈簧縮回,落定瞬間整卡左右微震 2px;pan超大字在停留期間由右往左線性橫移,超出舞台的部分被裁切;gradient用 blur 進場,**關鍵字**套漸層文字並掃過一次。 - 順序:eyebrow 先以寬字距淡入 300ms,接著 headline,sub 在 headline 進場完成後 200ms 淡入。
- 節奏變數:
--wb-kts-blur-duration(700ms)、--wb-kts-stagger(60ms)、--wb-kts-hold(2200ms)、--wb-kts-crossfade(500ms)、--wb-kts-sweep-duration(1200ms)、--wb-kts-gradient(藍→紫→粉的線性漸層)。可在外層或全域覆寫。 - autoplay:以
requestAnimationFrame計時,舞台不在畫面內(IntersectionObserver)時暫停;loop關閉時播完停在最後一張,按鈕變成「重播」。時間碼依實際經過時間跑。 - scroll:外層高度為卡數乘上區段高度,舞台
sticky置頂,依捲動進度決定目前卡片;往前捲才播進場,往回捲直接顯示該卡最終態。時間碼依捲動進度換算。放在固定高度的捲動框裡時,用scrollContainer指定該框。
可及性
- 每張卡是
role="group"、aria-roledescription="字幕卡",並以「第 n 張,共 N 張」標示;非目前卡片設為aria-hidden - 文字都是真實文字;逐詞拆分時另有一份完整句子給螢幕閱讀器,拆開的 span 設為
aria-hidden - HUD 為純裝飾,整層
aria-hidden - autoplay 時右下角有一顆可聚焦的暫停/播放按鈕(符合 WCAG 2.2.2),帶
aria-label與 focus-visible 外框 - 系統開啟「減少動態效果」時,所有進場改為 300ms 淡入,
pan不移動、punch不微震、HUD 閃爍點停止,背景硬切改為淡接