使用 G6 绘制流程图(Flowchart)或架构图(Architecture Diagram),与绘制社交网络图(力导向图)的逻辑完全不同。
社交网络图追求的是“节点不重叠,看着均匀”;而流程图和架构图追求的是**“层级分明、方向统一、模块嵌套”**。
要实现这一点,你需要掌握三个核心概念的组合拳:Dagre 布局 + Polyline 连线 + Combo 分组。
1. 核心思维模型
在 G6 中生成架构图,不是“画”出来的,而是“算”出来的。
-
方向感: 使用 Dagre 层次布局算法。它可以自动把节点按
上->下或左->右的依赖关系排列,不需要你手动指定 (x, y)。 -
规整感: 边(Edge)不能是直线,必须是 折线(Polyline),且通常是正交的(直角拐弯),看起来才像工程图。
-
嵌套感: 架构图中常见的“VPC包含子网,子网包含服务器”,在 G6 中对应的概念叫 Combo。
2. 关键配置详解(基于 G6 v5)
A. 布局:Dagre 是唯一的真神
不要试图自己去算坐标,一定要用 Dagre。它是专门用于有向图(Directed Graph)分层布局的算法。
JavaScript
const layout = {
type: 'dagre',
rankdir: 'TB', // 布局方向:'TB' (Top-Bottom) 自上而下,或 'LR' (Left-Right) 从左到右
align: 'UL', // 对齐方式:'UL' (Upper Left)
nodesep: 50, // 同一层节点间的水平间距
ranksep: 70, // 层与层之间的垂直间距
controlPoints: true, // 允许布局算法设置边的控制点(对折线很重要)
};
B. 节点:使用矩形与锚点
架构图的节点通常是矩形(Rect),并且连线最好连接在节点的“上下左右”四个中点上,而不是圆心,这样更整洁。
-
Shape:
rect -
Ports (连接桩): 必须指定连接点,否则线会穿过矩形中心。
C. 边:正交折线
流程图的线必须拐直角。
-
Type:
polyline(折线) -
Router:
orth(正交路由),让线自动寻找直角路径避开节点。
3. 实战代码:自动生成微服务架构图
假设我们要画一个经典的架构:网关 -> 业务服务集群 (含多个服务) -> 数据库。
JavaScript
import { Graph } from '@antv/g6';
// 1. 数据结构:必须包含 Combos 来表示“集群”或“分组”
const data = {
nodes: [
{ id: 'gateway', data: { label: 'API Gateway', type: 'entry' } },
{ id: 'service-a', data: { label: 'Order Service' }, combo: 'k8s-cluster' }, // 属于 combo
{ id: 'service-b', data: { label: 'User Service' }, combo: 'k8s-cluster' },
{ id: 'db-primary', data: { label: 'MySQL Master' }, combo: 'db-cluster' },
{ id: 'db-slave', data: { label: 'MySQL Slave' }, combo: 'db-cluster' },
],
edges: [
{ source: 'gateway', target: 'service-a' },
{ source: 'gateway', target: 'service-b' },
{ source: 'service-a', target: 'db-primary' },
{ source: 'service-b', target: 'db-primary' },
{ source: 'db-primary', target: 'db-slave', data: { label: 'Sync' } },
],
// 定义分组(容器)
combos: [
{ id: 'k8s-cluster', data: { label: 'K8s Cluster (App)' } },
{ id: 'db-cluster', data: { label: 'Database Zone' } },
],
};
// 2. 初始化图实例
const graph = new Graph({
container: 'container',
width: 1000,
height: 800,
// --- 关键配置开始 ---
// 布局:使用 Dagre 实现流程化排列
layout: {
type: 'dagre',
rankdir: 'LR', // 从左到右流向
nodesep: 30,
ranksep: 50,
sortByCombo: true, // 关键:让布局算法感知 Combo,不要把分组打散
},
// 节点通用样式
node: {
style: {
size: [120, 40], // 矩形宽高
shape: 'rect', // 形状
radius: 4, // 圆角
stroke: '#40a9ff',
fill: '#e6f7ff',
ports: [ // 定义四个连接点,保证连线规整
{ placement: 'top' },
{ placement: 'right' },
{ placement: 'bottom' },
{ placement: 'left' },
],
},
},
// 边通用样式
edge: {
type: 'polyline', // 折线
style: {
router: {
type: 'orth', // 正交路由:强迫线走直角
},
stroke: '#a0c5e8',
lineWidth: 2,
endArrow: true, // 箭头
radius: 10, // 拐角处的圆角,让折线不那么生硬
},
},
// 分组通用样式
combo: {
type: 'rect', // 分组也是矩形
style: {
fill: '#f0f5ff',
stroke: '#adc6ff',
lineDash: [5, 5], // 虚线边框,表示逻辑分组
radius: 8,
padding: [20, 10, 10, 10], // 这里的 padding 是为了给 Combo 的 Label 留位置
},
},
// 交互:允许折叠分组
behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element', 'collapse-expand-combo'],
});
graph.setData(data);
graph.render();
4. 进阶技巧:让图“专业”起来的细节
如果只是上面的代码,画出来的图只能算“能看”。要达到专业架构图(类似 Visio 或 Draw.io 的效果),需要处理以下细节:
1. 视觉区分(Mapper)
架构图中不同角色的节点样子应该不一样。比如数据库是圆柱体,网关是菱形或特殊颜色。
JavaScript
// 在 render 之前配置
graph.setOptions({
node: {
style: (d) => {
// 针对不同类型做特殊处理
if (d.data.type === 'entry') {
return { fill: '#722ed1', stroke: '#722ed1', labelFill: '#fff' };
}
return {}; // 其他保持默认
}
}
});
2. 解决“连线乱穿”问题
Dagre 布局有时会导致连线穿过节点。
-
方案: 增加
layout中的ranksep(层间距)。 -
高级方案: 如果 G6 的内置路由(orth)效果不好,可以尝试 G6 的插件或自定义 Edge,强制连线先从 Right 端口出来,再寻找路径。
3. 复杂的节点内容(HTML Node)
如果你的架构图节点需要显示:IP 地址、CPU 占用率进度条、报警图标。普通的 rect 形状很难画。
-
使用 React/HTML 节点:
在 v5 中,你可以定义一个 React 组件作为节点。
JavaScript
import { ReactNode } from '@antv/g6-extension-react'; // 注册 register(ReactNode, 'react-card'); // 使用 node: { type: 'react-card', style: { component: (data) => <MyServiceCard status={data.status} title={data.label} /> } }注意:HTML 节点性能比 Canvas 节点差,如果图中有上千个节点,慎用。但在架构图通常只有几十个节点,完全没问题。
5. 总结与建议
-
场景判断: 如果你的数据是从后端 API 拿回来的(例如:K8s 的拓扑、调用链追踪),G6 + Dagre + Combo 是完美解法,全自动生成。
-
反直觉提醒: 如果你是想做一个工具,让用户自己拖拽生成流程图,千万不要用 G6,请出门左转用 X6。X6 才是为此而生的(带有吸附对齐、手动连线路由等编辑特性)。
下一步行动:
你想尝试生成一个简单的垂直(Top-Bottom)流程图,还是一个包含分组嵌套的复杂架构图?我可以给你写一个具体的 CodeSandbox 在线示例配置供你复制。