資料視覺敘事
互動系統架構圖
可平移縮放的系統架構圖:節點與連線由資料產生,群組可展開收合,選取節點時高亮相連路徑並顯示詳情。
把服務、資料庫、佇列與外部依賴畫成一張可以實際操作的架構圖:只要給節點與連線的資料,元件會依連線方向自動分層排版,畫出藍圖風的點格背景、語意色連線與圖例。拖曳平移、滾輪或雙指縮放,群組可以展開成框、也能收合成一張卡片(收合後連到群組內的邊會改連到群組本身)。點選任一節點,相連的邊與鄰居保持清楚、其餘淡到 25%,右側滑出詳情面板列出上下游,點一下就跳過去。右下有小地圖與「符合畫面」。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add "https://webberui.com/r/system-map-canvas.json?t=<安裝 token>"Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
1.2
編輯中的呼叫預設屬性
<SystemMapCanvas/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add "https://webberui.com/r/system-map-canvas.json?t=<安裝 token>"或在 components.json 設定 registries 後,改用 @webberui/system-map-canvas 安裝。
使用
import {
SystemMapCanvas,
type SystemMapEdge,
type SystemMapNode,
} from "@/components/ui/system-map-canvas";
const nodes: SystemMapNode[] = [
{ id: "web", label: "Web 用戶端", kind: "client" },
{ id: "gateway", label: "API Gateway", kind: "service" },
{ id: "orders", label: "訂單域", kind: "group" },
{ id: "order", label: "訂單服務", kind: "service", parent: "orders" },
{ id: "queue", label: "通知佇列", kind: "queue", parent: "orders" },
{ id: "db", label: "主資料庫", kind: "database", description: "訂單的唯一真實來源" },
];
const edges: SystemMapEdge[] = [
{ from: "web", to: "gateway", kind: "sync", label: "HTTPS" },
{ from: "gateway", to: "order", kind: "sync" },
{ from: "order", to: "queue", kind: "async", label: "訂單事件" },
{ from: "order", to: "db", kind: "data" },
{ from: "order", to: "gateway", kind: "error" },
];
<SystemMapCanvas
nodes={nodes}
edges={edges}
defaultExpanded={["orders"]}
edgeStyle="curved"
onSelectedChange={(id) => console.log("selected", id)}
/>;Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
nodes | SystemMapNode[] | — | 節點清單 |
edges | SystemMapEdge[] | — | 連線清單;指到不存在節點的連線會被略過 |
layout | "auto" | "manual" | "auto" | auto 依連線自動分層排版;manual 使用節點的 x/y(缺座標的節點退回自動位置) |
expanded | string[] | — | 受控:目前展開的群組 id |
defaultExpanded | string[] | [] | 非受控:初始展開的群組 id |
onExpandedChange | (expanded: string[]) => void | — | 展開或收合群組時回呼 |
selectedId | string | null | — | 受控:目前選取的節點 id |
defaultSelectedId | string | null | null | 非受控:初始選取的節點 id |
onSelectedChange | (id: string | null) => void | — | 選取改變時回呼(取消選取時為 null) |
minZoom | number | 0.3 | 最小縮放倍率 |
maxZoom | number | 2.5 | 最大縮放倍率 |
edgeStyle | "orthogonal" | "curved" | "orthogonal" | 連線樣式:正交折線或平滑三次曲線 |
showMinimap | boolean | true | 初始是否顯示小地圖;控制列的按鈕可再切換 |
surface | "dark" | "auto" | "dark" | dark 固定暗色藍圖風;auto 跟隨站台的亮暗主題 |
height | number | 420 | 畫布高度(px) |
className | string | — | 透傳到最外層容器 |
SystemMapNode
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
id | string | — | 節點唯一識別碼,edges 與 parent 以此指涉 |
label | string | — | 卡片上的名稱 |
kind | "service" | "database" | "queue" | "client" | "external" | "group" | "service" | 決定圖示與副標;有子節點的節點一律視為群組 |
parent | string | — | 所屬群組的 id(可巢狀) |
description | string | — | 詳情面板裡的描述 |
x | number | — | layout="manual" 時卡片左上角的世界座標 x |
y | number | — | layout="manual" 時卡片左上角的世界座標 y |
SystemMapEdge
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
id | string | — | 連線識別碼;未提供時自動產生 |
from | string | — | 起點節點 id |
to | string | — | 終點節點 id |
label | string | — | 連線中點的小標籤 |
kind | "sync" | "async" | "data" | "error" | "sync" | 語意類型:同步呼叫(實線)、非同步訊息(流動虛線)、資料讀寫、錯誤回報(點線) |
另外具名匯出 SystemMapNodeKind、SystemMapEdgeKind 與 SystemMapCanvasProps 型別。
CSS 變數
| 變數 | 預設值 | 說明 |
|---|---|---|
--wb-system-map-canvas-sync | #d4d4d4 | 同步呼叫連線色(surface="auto" 亮色主題下退回 #a3a3a3) |
--wb-system-map-canvas-async | #2dd4bf | 非同步訊息連線色 |
--wb-system-map-canvas-data | #f59e0b | 資料讀寫連線色 |
--wb-system-map-canvas-error | #fb7185 | 錯誤回報連線色 |
--wb-system-map-canvas-accent | #2dd4bf | 選取節點的強調色、焦點外框與小地圖視窗框 |
--wb-system-map-canvas-flow | 1.2s | 非同步虛線流動一個循環的時間 |
細節
- 自寫的分層排版:
layout="auto"時依連線的拓撲深度決定欄位、同欄以重心法來回排序四次減少交叉。用戶端(kind="client")一律當入口放在最左欄,錯誤回報邊只畫不參與分層,其餘的環以 DFS 找出回邊略過,所以回饋迴路不會把整張圖拉歪 - 群組是巢狀排版:展開的群組先把自己的子節點排好,再當成一個大節點參與上一層,因此群組框不會和外面的節點重疊。收合時群組變回一張卡片,連到群組內任一節點的邊會改連到群組本身,重複的邊合併成一條
- 展開動畫:子節點從群組中心以彈簧(stiffness 260、damping 26)散開到排版位置,連線路徑同步插值;收合時反向收回群組卡片
- 平移縮放:拖曳背景平移(pointer capture);滾輪以游標為中心縮放,觸控板 pinch(ctrl + 滾輪)與雙指觸控也支援;按鈕、鍵盤與滾輪的移動以彈簧(stiffness 300、damping 35)平滑,拖曳則直接跟手。背景格線隨縮放同步,每 5 小格一條主格線
- 小地圖:顯示所有可見節點與目前的視窗框,拖曳視窗框即可移動畫面,點框外會先把視窗中心移過去
- 元件只在畫面內時播放非同步虛線的流動動畫,捲出畫面即暫停
可及性
- 外層為
role="application"、aria-roledescription="系統架構圖",並以aria-describedby指向一段操作說明 - 畫布可聚焦:方向鍵平移 40px、
+/-縮放、0符合畫面;Tab 依欄位順序走訪每個節點(button),聚焦到畫面外的節點時會自動平移帶進視窗 - Enter 選取節點,在群組上按空白鍵展開或收合,Esc 取消選取並關閉詳情面板;每個節點的
aria-label包含名稱、類型與上下游數量(例如「付款服務,服務,1 個上游,2 個下游」) - 另有一份
sr-only的節點與連線清單,連線依「起點 到 終點,類型:標籤」逐條列出 - 所有按鈕都有
focus-visible外框;圖例與小地圖為純視覺輔助(aria-hidden) - 使用者系統開啟「減少動態效果」時,非同步連線改為靜止虛線不流動,平移、縮放、展開收合與詳情面板都直接跳到終態