資料視覺敘事

儀表盤

指針儀表盤:spring 擺動指針、分段色弧、數值滾動。

SVG 半圓儀表盤,指針以低阻尼 spring 轉到目標值、帶過衝回穩的擺動感;分段色弧(綠黃紅可自訂 stops)搭配刻度線,中央數值與指針共用同一條 spring 同步滾動,指針尚未到達的色段會降低透明度。

把這個效果裝進你的專案

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

npx webberui@latest add gauge-meter

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

Gauge Meter 是用 React、SVG 與 Motion 的 useSpring 做的指針儀表盤(gauge chart、速度錶、半圓儀表)元件:半圓分段色弧加上刻度,指針以帶過衝的彈簧擺到目標值,中央數字同步滾動,下方顯示目前所在色段的狀態文字。

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

72
240
0
編輯中的呼叫預設屬性
<GaugeMeter/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

適用情境

  • 系統監控儀表板的 CPU、記憶體、磁碟使用率
  • 網站效能或 SEO 健康度分數
  • IoT 裝置的溫度、濕度、壓力讀數
  • 業績達成率、客戶滿意度這類有「良好/注意/警戒」區間的指標
  • 不適合:只需要單純百分比進度、不需要刻度與指針時,Circular Progress 更簡潔

安裝

npx webberui@latest add https://webberui.com/r/gauge-meter.json

或在 components.json 設定 registries 後,改用 @webberui/gauge-meter 安裝。

使用

import { GaugeMeter } from "@/components/ui/gauge-meter";

<GaugeMeter
  value={72}
  unit="%"
  label="CPU 使用率"
  stops={[
    { to: 60, color: "#10b981", label: "順暢" },
    { to: 85, color: "#f59e0b", label: "偏高" },
    { to: 100, color: "#ef4444", label: "過載" },
  ]}
/>

範例

輪詢 API 即時更新

value 每次改變,指針都會從目前位置彈到新值,適合接上定時輪詢的監控資料。

"use client";

import * as React from "react";
import { GaugeMeter } from "@/components/ui/gauge-meter";

export function MemoryGauge() {
  const [usage, setUsage] = React.useState(0);

  React.useEffect(() => {
    const load = () =>
      fetch("/api/metrics/memory")
        .then((r) => r.json())
        .then((d: { percent: number }) => setUsage(d.percent));
    load();
    const id = setInterval(load, 5000);
    return () => clearInterval(id);
  }, []);

  return <GaugeMeter value={usage} unit="%" label="記憶體使用率" decimals={1} />;
}

自訂範圍與色段

min、max 不必是 0 到 100。stops 依 to 排序,每段的 label 會在指針落入該段時顯示。從元件匯出的 GaugeStop 型別可以用來宣告設定。

import { GaugeMeter, type GaugeStop } from "@/components/ui/gauge-meter";

const tempStops: GaugeStop[] = [
  { to: 18, color: "#3b82f6", label: "偏冷" },
  { to: 26, color: "#10b981", label: "舒適" },
  { to: 40, color: "#ef4444", label: "過熱" },
];

<GaugeMeter value={23.5} min={0} max={40} stops={tempStops} unit="°C" label="機房溫度" decimals={1} />

多個儀表並排

size 控制寬度,高度依 200:148 比例縮放,適合在格狀版面裡排成一列。

<div className="grid grid-cols-3 gap-6">
  <GaugeMeter size={180} value={42} unit="%" label="CPU" />
  <GaugeMeter size={180} value={68} unit="%" label="記憶體" />
  <GaugeMeter size={180} value={91} unit="%" label="磁碟" />
</div>

Props

Prop型別預設值說明
valuenumber—目標值,變更時指針以 spring 擺動過去(帶過衝回穩)
minnumber0量表最小值
maxnumber100量表最大值
stopsGaugeStop[]綠黃紅預設分段色弧設定,每段為 { to, color, label? },未提供時使用 60% / 85% / 100% 的綠黃紅
unitstring—數值後方的單位文字,例如 "%"、"km/h"
labelstring—儀表標題,顯示於儀表下方
sizenumber240儀表寬度(px),高度依 200:148 比例自動縮放
decimalsnumber0中央數值顯示的小數位數
classNamestring—透傳到外層容器

GaugeStop:to 為此色段的結束值(各段需遞增,最後一段建議等於 max)、color 為任何合法 CSS 顏色、label 為當前值落在此段時顯示的狀態文字。

可及性

  • 容器使用 role="meter" 搭配 aria-valuemin / aria-valuemax / aria-valuenow 與 aria-valuetext,輔助科技朗讀的是目標值而非動畫中間值
  • SVG 本體標記 aria-hidden,避免與 meter 語意重複朗讀
  • 使用者系統開啟「減少動態效果」時,指針與數字直接跳至目標值,不播放 spring 擺動
  • 數值使用 tabular-nums 等寬數字,滾動時版面不抖動

常見問題

可以在 Next.js App Router 使用嗎?

可以。原始碼已經有 "use client",在 Server Component 頁面直接 import 即可。伺服器端與首次渲染時指針停在 min,掛載後才彈到目標值。

超出 min/max 的值會怎樣?

value 會被夾在 min 到 max 之間。指針在彈簧過衝時可以稍微超出兩端(約 4%),中央數字則始終鎖在範圍內。

沒有傳 stops 時,色段怎麼分?

預設是綠、黃、紅三段,分界在範圍的 60% 與 85%,狀態文字分別是「良好」、「注意」、「警戒」。

可以讓寬度跟著容器變化嗎?

size 是以 px 寫在外層的 inline width,SVG 本身是 w-full。需要流動寬度時,可以在原始碼裡把 style={{ width: size }} 改成你要的寬度設定。

螢幕閱讀器讀到的是什麼?

外層是 role="meter",帶有 aria-valuemin、aria-valuemax、aria-valuenow 與 aria-valuetext,讀的是目標值而非動畫中的數字;沒有 label 時 aria-label 預設為「儀表」。依賴是 motion、clsx、tailwind-merge。