資料視覺敘事
即時頻譜監視器
即時捲動的頻譜/熱度帶:canvas 逐幀繪製頻段強度瀑布圖,可暫停、hover 讀值,離開視口自動停止。
把連續變化的頻段強度畫成一塊儀表:上方是當前幀的頻譜條,每根條上有慢慢落下的峰值保持點;下方是瀑布圖,每一幀新增一列像素從頂端進入、整張往下捲,顏色依強度映射到色階,一眼看出哪個頻段一直在響、哪個是間歇出現。適合振動監測、音訊分析、網路流量或任何「頻段 × 時間」的即時資料。兩張 canvas 逐幀繪製,離開視口或分頁隱藏時自動停止,不會在背景空轉。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add "https://webberui.com/r/spectrum-monitor.json?t=<安裝 token>"Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
30
120
1.6
編輯中的呼叫預設屬性
<SpectrumMonitor/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add "https://webberui.com/r/spectrum-monitor.json?t=<安裝 token>"或在 components.json 設定 registries 後,改用 @webberui/spectrum-monitor 安裝。
使用
import { SpectrumMonitor } from "@/components/ui/spectrum-monitor";
// 不給資料來源時使用內建的決定性產生器
<SpectrumMonitor title="頻譜監視器" bins={64} minHz={20} maxHz={20000} />;
// 接自己的資料:回傳長度為 bins、值域 0–1 的陣列
<SpectrumMonitor
title="感測器 A3"
bins={96}
minHz={10}
maxHz={5000}
source={(t, bins) => readLatestBands(bins)}
onPausedChange={(paused) => console.log(paused ? "已暫停" : "繼續")}
/>;Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
bins | number | 64 | 頻段數量(頻譜條數、瀑布圖每列像素數),範圍 4–512 |
source | (t: number, bins: number) => number[] | — | 自訂資料來源:給定模擬時間 t(秒)與頻段數,回傳 0–1 強度陣列;未提供時用內建決定性產生器(數個正弦峰 + 以幀序號 hash 的雜訊) |
frames | number[][] | — | 靜態資料回放,每個元素是一幀,依序循環;優先於 source |
fps | number | 30 | 每秒產生幾幀,以 requestAnimationFrame 累積時間節流,範圍 1–120 |
history | number | 120 | 瀑布圖保留的列數(一幀一列),範圍 10–600 |
colorStops | string[] | — | 強度色階(由低到高),任何 CSS 顏色字串;未提供時讀取 --wb-spectrum-monitor-low/-mid/-high/-peak 變數,最頂端固定為白色 |
paused | boolean | — | 受控的暫停狀態;未提供時由元件內部管理 |
defaultPaused | boolean | false | 非受控模式的初始暫停狀態 |
onPausedChange | (paused: boolean) => void | — | 暫停狀態變動時回呼 |
minHz | number | 20 | 頻率刻度下限(Hz),只用於刻度與讀值換算 |
maxHz | number | 20000 | 頻率刻度上限(Hz) |
logScale | boolean | true | 頻段是否以對數刻度分布 |
labels | string[] | — | 自訂底部刻度標籤(等距排列);未提供時依 minHz/maxHz 自動產生 |
height | number | 320 | 繪圖區總高度(px),約 32% 給頻譜條、其餘給瀑布圖 |
title | string | "頻譜監視器" | 狀態列標題 |
surface | "dark" | "auto" | "dark" | 外框配色:dark 固定暗色儀表、auto 跟隨網站深淺主題;繪圖區永遠是暗色螢幕 |
label | string | — | 繪圖區 role="img" 的 aria-label;未提供時依標題、頻段數與頻率範圍自動產生 |
className | string | — | 透傳到最外層容器 |
另外具名匯出 getSpectrumBinHz(i, bins, minHz, maxHz, logScale)(頻段 i 的中心頻率,方便自訂 source 時對齊頻率)與 SpectrumMonitorProps、SpectrumMonitorSurface 型別。
CSS 變數
| 變數 | 預設值 | 說明 |
|---|---|---|
--wb-spectrum-monitor-low | #171717 | 色階最低端(neutral-900) |
--wb-spectrum-monitor-mid | #0f766e | 色階中低段(teal-700) |
--wb-spectrum-monitor-high | #2dd4bf | 色階中高段(teal-400) |
--wb-spectrum-monitor-peak | #fcd34d | 色階高段(amber-300),再往上到白色 |
--wb-spectrum-monitor-pulse | 1.6s | LIVE 指示燈呼吸週期 |
細節
- 兩張 canvas:頻譜畫布依容器尺寸乘上
min(devicePixelRatio, 2)重設解析度(ResizeObserver);瀑布畫布的解析度就是資料解析度(bins×history),由瀏覽器平滑放大成熱度帶 - 瀑布捲動不重繪整張:每產生一幀,先用
drawImage把畫布自身往下位移一列,再只畫最新那一列;色階事先預算成 256 色查找表 - 節流:rAF 每次累積經過時間,滿
1 / fps秒才產生一幀;分頁切回時單次時間上限 0.25 秒,避免一口氣補畫太多幀 - 峰值保持:每根頻譜條上的白點取「目前值」與「上一幀峰值 × 0.96」較大者,慢慢落下
- 讀值:hover 頻譜或瀑布圖顯示十字線與讀值卡——頻率、強度(20·log10 換算的 dB 與百分比)、這一列是幾秒前;暫停時畫面凍結,讀值仍可用
- 自動停止:IntersectionObserver 偵測離開視口、
visibilitychange偵測分頁隱藏時取消 rAF;卸載時取消 rAF 並斷開所有 observer - 初始快照:掛載時預跑
history幀,瀑布圖一開始就是滿的,hover 立即有資料
可及性
- 繪圖區為
role="img",aria-label描述標題、頻段數與頻率範圍;兩張 canvas 都是aria-hidden - 另有
sr-only的aria-live="polite"區域,每 5 秒更新一次「目前峰值 1.2 kHz,-12 dB」,暫停時停止更新 - 暫停鈕為
type="button"並帶aria-pressed;繪圖區可用 Tab 聚焦(focus-visible外框),聚焦在元件內時按空白鍵切換暫停,點擊繪圖區也可暫停/繼續 - 使用者系統開啟「減少動態效果」時不自動播放,只畫一張預跑
history幀的靜態快照,LIVE 燈不呼吸;按下播放才開始,且幀率降為最多 10 fps