資料視覺敘事
圖解套件
資料驅動的十一種 SVG 圖解:樞紐分流、泳道序列、循環、時間軸、放射分支、漏斗、層級金字塔、錨點標註、分支揭露、四象限與文氏圖,進場皆以描線與節點依序登場。
簡報、說明頁、產品導覽裡最常見的十一種圖解,全部用資料描述:給節點與關係,元件負責排版與進場動畫。共用同一套動畫契約——連線與外框以描線畫出、節點依拓樸順序彈出;滑過或聚焦節點時,只留下相關路徑、其餘淡出,並顯示補充說明。外框 DiagramKit 提供標題、說明、圖例與播放/重播,子圖以 DiagramKit.Venn 這類靜態屬性取用。所有圖都是 viewBox 自適應寬度的 SVG,中文標籤會自動折行。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add "https://webberui.com/r/diagram-kit.json?t=<安裝 token>" 還沒有專案,或安裝遇到問題?看快速開始 →
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
import * as React from "react";
export default function Example() {
return (
<div className="flex min-h-[320px] w-full items-center justify-center p-6"> </div>
);
}
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
npx webberui@latest add "https://webberui.com/r/diagram-kit.json?t=<安裝 token>"或在 components.json 設定 registries 後,改用 @webberui/diagram-kit 安裝。
import { DiagramKit } from "@/components/ui/diagram-kit";
<DiagramKit title="訂單中心如何分流" legend={[{ label: "匯入" }, { label: "分流" }]}>
<DiagramKit.HubRouting
hub={{ id: "hub", label: "訂單中心", detail: "每日約 1,200 筆" }}
spokes={[
{ id: "web", label: "官網", side: "in" },
{ id: "store", label: "門市", side: "in" },
{ id: "wh", label: "倉儲", side: "out" },
{ id: "cs", label: "客服", side: "out" },
]}
/>
</DiagramKit>;
<DiagramKit trigger="mount" accent="#0ea5e9">
<DiagramKit.Venn
sets={[
{ id: "design", label: "設計" },
{ id: "eng", label: "工程" },
{ id: "biz", label: "商業" },
]}
intersections={[
{ sets: ["design", "eng", "biz"], words: ["好用", "做得出來", "賺得到錢"] },
]}
/>
</DiagramKit>;
子圖也可以不包 DiagramKit 單獨使用,此時視為掛載即播放。
| Prop | 型別 | 預設值 | 說明 |
|---|
title | string | — | 圖的標題 |
description | string | — | 標題下方的說明 |
legend | DiagramLegendItem[] | — | 圖例;未指定顏色時依序取 series 色票 |
playing | boolean | — | 受控的播放狀態(true 代表已觸發進場) |
defaultPlaying | boolean | false | 非受控模式的初始播放狀態 |
onPlayingChange | (playing: boolean) => void | — | 播放狀態變動時回呼 |
trigger | "inView" | "mount" | "manual" | "inView" | 進場觸發:捲入視窗 25%、掛載即播、或只由按鈕/playing 控制 |
drawDuration | number | 700 | 單段描線時長(毫秒);未提供時讀 --wb-diagram-draw |
stagger | number | 90 | 節點依序登場的間隔(毫秒);未提供時讀 --wb-diagram-stagger |
accent | string | #3b82f6 | 強調色,寫入 --wb-diagram-accent |
series | string[] | 強調色 + 4 色 | 自訂色票,第一色為主色 |
controls | boolean | true | 是否顯示播放/重播按鈕 |
children | ReactNode | — | 放一個子圖 |
className | string | — | 透傳到最外層容器 |
每個子圖都另有 interactive?: boolean(預設 true,hover/focus 高亮與 tooltip)、label?: string(svg 的無障礙名稱)與 className?: string。下表只列各自的資料 props;通用節點型別 DiagramNode 為 { id, label, detail? }。
| 欄位 | 型別 | 預設值 | 說明 |
|---|
hub | DiagramNode | — | 中央樞紐 |
spokes | HubSpoke[] | — | 輻條節點;side: "in" 在左側匯入、"out" 在右側分流 |
pulse | boolean | true | 進場完成後沿線流動的脈衝光點 |
| 欄位 | 型別 | 預設值 | 說明 |
|---|
lanes | DiagramNode[] | — | 泳道(參與者),由左至右 |
messages | SequenceMessage[] | — | 依時間順序的訊息 { from, to, label, detail? };from 等於 to 時畫自我迴圈 |
| 欄位 | 型別 | 預設值 | 說明 |
|---|
steps | DiagramNode[] | — | 依循環順序的步驟,最後一步接回第一步 |
center | string | — | 圓心標題 |
| 欄位 | 型別 | 預設值 | 說明 |
|---|
events | TimelineEvent[] | — | { id?, date, title, detail? },依時間先後 |
orientation | "auto" | "horizontal" | "vertical" | "auto" | auto 在容器寬度小於 480px 時改為垂直 |
| 欄位 | 型別 | 預設值 | 說明 |
|---|
center | DiagramNode | — | 中心節點 |
branches | RadialBranch[] | — | 第一層分支(含 children 第二層),從正上方順時針排列 |
| 欄位 | 型別 | 預設值 | 說明 |
|---|
stages | FunnelStage[] | — | { id?, label, value, detail? },由上到下 |
particles | boolean | true | 進場後粒子被吸入往下流動 |
valueFormatter | (value: number) => string | 千分位 | 數值格式化 |
| 欄位 | 型別 | 預設值 | 說明 |
|---|
tiers | DiagramNode[] | — | 層級;tiers[0] 為最底層,最後一項為頂端 |
| 欄位 | 型別 | 預設值 | 說明 |
|---|
anchors | CalloutAnchor[] | — | { id, x, y, label, detail?, side? };x、y 為底圖的百分比 0–100 |
children | ReactNode | — | 底圖內容(截圖、卡片、插圖) |
| 欄位 | 型別 | 預設值 | 說明 |
|---|
root | BranchNode | — | 樹根;children 為子節點 |
expandedIds | string[] | — | 受控的已展開節點 id |
defaultExpandedIds | string[] | [root.id] | 非受控模式的初始展開節點 |
onExpandedChange | (ids: string[]) => void | — | 展開狀態變動時回呼 |
interactive={false} 時整棵樹全部展開、不可切換。
| 欄位 | 型別 | 預設值 | 說明 |
|---|
xAxis | QuadrantAxis | — | 橫軸兩端文字 { low, high } |
yAxis | QuadrantAxis | — | 縱軸兩端文字 { low, high } |
quadrants | [string, string, string, string] | — | 象限名稱,順序為左上、右上、左下、右下 |
items | QuadrantItem[] | — | 受控的項目 { id, label, x, y, detail? },x、y 為 0–100 |
defaultItems | QuadrantItem[] | [] | 非受控模式的初始項目 |
onItemsChange | (items: QuadrantItem[]) => void | — | 拖曳或方向鍵移動後回呼 |
| 欄位 | 型別 | 預設值 | 說明 |
|---|
sets | VennSet[] | — | 2 或 3 個集合(超過只取前三個) |
intersections | VennIntersection[] | [] | { sets, label?, words?, detail? };words 多於一個時輪替顯示 |
wordInterval | number | 1800 | 交集字詞輪替間隔(毫秒) |
另外具名匯出 wrapText(CJK 友善的換行估算)、DIAGRAM_SERIES 與上述所有型別。
- 共用動畫契約:連線與外框的
pathLength 從 0 到 1(緩動 [0.65, 0, 0.35, 1]),節點以 spring(stiffness 320、damping 26)從 0.6 倍放大淡入,依拓樸順序間隔 stagger 登場
- 節奏變數:
--wb-diagram-draw(700ms)、--wb-diagram-stagger(90ms)、--wb-diagram-accent(#3b82f6)、--wb-diagram-dim(0.25,高亮時其餘元素的透明度);props 優先於變數
- 重播:外框的「重播」按鈕會重新掛載子圖,整段進場從頭再跑一次
- 中文折行:標籤寫在 SVG
text 裡,依字元寬度估算換行(中文逐字可斷、英文以單字為單位、行首避開標點),超過行數以刪節號收尾
- 文氏圖:外框圓以虛線描出後從分開的位置靠攏,交集區用 clip-path 填色亮起;交集文字每 1.8 秒交叉淡接
- 漏斗:粒子以確定性分布從上方被吸入,部分在中途層「被吸收」,對應各層的流失;每層右側顯示相對上一層的轉換率
- 錨點標註:底圖可以是任意內容,元件量測底圖位置後把標籤分到左右兩側並避免重疊,引線以折線連到錨點
- 每個子圖的 SVG 都有
title 與 desc,並另輸出一份 sr-only 結構化文字(清單或表格),螢幕閱讀器可完整讀到資料
- 節點可用 Tab 聚焦,聚焦時與 hover 相同會高亮相關路徑;鍵盤焦點另畫外框
- 分支揭露的節點是
role="button" 並帶 aria-expanded,按 Enter 或空白鍵展開/收合(IME 組字中的 Enter 會被忽略)
- 四象限的項目可拖曳,也可聚焦後用方向鍵移動(按住 Shift 一次移動 10)
- tooltip 為純視覺輔助(
aria-hidden),同樣資訊已在 sr-only 文字中
- 使用者系統開啟「減少動態效果」時,所有圖直接顯示終態:沒有描線、沒有節點彈出、沒有粒子與脈衝光點,文氏圖也不輪播交集文字