資料視覺敘事
堆疊長條圖
多層堆疊長條圖 React 元件:點擊圖例收合某一層,其餘層以彈簧下沉補位、Y 軸刻度同步重算並補間,hover 或方向鍵檢視該欄各層數值與占比。
把每一欄拆成多層來看組成的長條圖。頂部圖例每層一顆切換按鈕(色點、名稱、全期合計),點一下該層高度收合到 0 並淡出,上方各層以彈簧下沉補位;Y 軸依目前可見層的最大堆疊和重新取整,格線同步滑到新位置、刻度數字補間到新值。滑過某欄時其餘欄淡到一半,tooltip 依堆疊順序由上而下列出各層數值與占比。純 SVG 自繪、不依賴圖表函式庫,寬度跟隨容器。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add stacked-column-chartPlayground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
300
260
600
編輯中的呼叫預設屬性
<StackedColumnChart/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add https://webberui.com/r/stacked-column-chart.json或在 components.json 設定 registries 後,改用 @webberui/stacked-column-chart 安裝。
使用
import { StackedColumnChart } from "@/components/ui/stacked-column-chart";
const series = [
{ key: "web", label: "官網" },
{ key: "store", label: "門市" },
{ key: "group", label: "團購" },
];
const data = [
{ label: "3 月", values: { web: 42, store: 31, group: 12 } },
{ label: "4 月", values: { web: 46, store: 29, group: 16 } },
{ label: "5 月", values: { web: 51, store: 33, group: 22 } },
];
<StackedColumnChart
series={series}
data={data}
formatValue={(v) => `${v} 萬`}
onHiddenKeysChange={(keys) => console.log("隱藏:", keys)}
/>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
series | StackedColumnSeries[] | — | 層的定義,依序由下往上堆疊 |
data | StackedColumnDatum[] | — | 每一欄的資料 |
hiddenKeys | string[] | — | 受控的隱藏層 key;未提供時由元件內部管理 |
defaultHiddenKeys | string[] | [] | 非受控模式的初始隱藏層 |
onHiddenKeysChange | (hiddenKeys: string[]) => void | — | 隱藏層變動時回呼;元件保證至少保留一層可見 |
height | number | 300 | 圖區高度(px,含 X 標籤),寬度跟隨容器 |
showTotals | boolean | true | 是否在每欄頂端顯示可見層的總數 |
formatValue | (value: number) => string | zh-TW 千分位 | 數值格式化(軸、總數、tooltip 共用),貨幣與單位在這裡加 |
stiffness | number | 260 | 彈簧剛性;提供時寫入 --wb-stacked-column-chart-stiffness |
duration | number | 600 | 進場生長時長(ms);提供時寫入 --wb-stacked-column-chart-duration |
ariaLabel | string | "堆疊長條圖" | 圖表的無障礙名稱,用於摘要與資料表標題 |
className | string | — | 透傳到最外層容器 |
StackedColumnSeries
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
key | string | — | 唯一識別碼,對應 data[].values 的鍵 |
label | string | — | 圖例與 tooltip 顯示名稱 |
color | string | — | 覆寫此層顏色;未提供時使用 --wb-stacked-column-chart-1 到 -5 |
StackedColumnDatum
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
label | string | — | X 軸標籤 |
values | Record<string, number> | — | 各層數值,缺值或負數視為 0 |
另外具名匯出 niceStackedScale(max),回傳與圖表相同的 Y 軸上限與刻度,方便在外部對齊其他圖表。
細節
- 配色走 CSS 變數:
--wb-stacked-column-chart-1到-5預設為 teal 由深到淺五階(#134e4a#0f766e#14b8a6#5eead4#ccfbf1),暗色模式自動換成較亮的一組;在任一祖先元素設定這五個變數即可整組覆寫,超過五層會循環使用。焦點框顏色讀--wb-stacked-column-chart-accent(預設#0d9488,暗色#2dd4bf)。 - 節奏也可外部覆寫:
--wb-stacked-column-chart-stiffness(預設 260,阻尼固定 30)控制收合補位與格線移動的彈簧,--wb-stacked-column-chart-duration(預設 600ms)控制進場生長;欄與欄之間間隔 40ms,刻度數字補間 400ms。 - 收合的層不會從 DOM 移除,而是高度歸零停在下方堆疊的頂端;重新展開時就從那個位置長出來,視覺上始終維持堆疊順序。
- 至少保留一層可見:只剩一層時該圖例按鈕設定
aria-disabled,點擊不會隱藏;受控模式傳入「全部隱藏」時第一層仍會顯示。 - 進場在圖表捲進畫面(
useInView,邊界 -10%)時才觸發,且只播一次;tooltip 固定寬度並夾在容器內,不會溢出卡片。
可及性
- 圖例是原生
button,以aria-pressed表示該層是否可見,Enter/空白鍵切換 - 圖區可聚焦(
tabIndex=0),←/→ 逐欄移動、Home/End 跳到首尾、Esc 收起 tooltip;目前欄的組成會透過aria-live區域朗讀 - SVG 帶
role="img"與包含欄數、可見層與最高合計的aria-label摘要,另附螢幕閱讀器專用的完整資料表(每欄、每層數值與可見層合計) - 可聚焦元素都有
focus-visible焦點框 - 使用者系統開啟「減少動態效果」時,整欄生長、層的收合補位與刻度補間都直接顯示終態,tooltip 仍可正常使用