G6 Grid 网格布局完全指南:从基础配置到防重叠、排序与定点布局实战
2026/9/23 15:50:35 网站建设 项目流程
  • 数据可视化
  • 前端
  • 图表库

【免费下载链接】G6

♾ A Graph Visualization Framework in JavaScript.

项目地址:https://gitcode.com/gh_mirrors/g6/G6
点击查看免费下载

导读

Grid(网格)布局是 G6(AntV G6,一个 JavaScript 图可视化框架)内置的一种非迭代布局,它将所有节点按行、列整齐地排布成网格状,特别适合矩阵/表格型数据可视化、仪表盘、数据字典等需要"规整有序"呈现的场景。本文以官方文档 GridLayout.en.md 为主线,结合仓库中的注册表、运行时与测试代码,系统讲解 Grid 布局的配置项、默认值、防重叠机制、排序策略以及动态更新布局的完整实战方案。

Grid 布局概述与适用场景

Grid 布局的核心能力是把节点放入一个规则的行列网格中,与力导向、圆形等强调拓扑关系的布局不同,Grid 布局不追求"还原关系",而是追求"排布整齐":

  • 支持根据节点数量、布局区域尺寸自动计算行数/列数,也可以手动指定rows/cols
  • 支持通过nodeSize/nodeSpacing进行碰撞检测,避免节点相互重叠;
  • 支持按节点属性排序,让数值更大的节点更靠近中心;
  • 支持通过position手动指定特定节点所在的单元格。

从仓库源码看,Grid 布局在 G6 中属于注册在案的内置布局(packages/g6/src/registry/build-in.ts#L166),其类型定义继承自BaseLayoutOptions并标注type: 'grid'(packages/g6/src/layouts/types.ts#L108-L110),实际算法由@antv/layout提供。典型适用场景

  • 矩阵、表格形式的数据可视化,例如班级座位表、机房机柜、仓库货位;
  • 需要把一组"互不关联"或"关系较弱"的节点进行规整陈列的场景;
  • 作为组合布局的兜底排版,或配合sortBy做集群分组展示。

快速上手:最小可用配置

最简单的 Grid 布局只需声明type: 'grid'并指定行列数即可。以下配置会生成 25 个节点(5×5 网格)与 20 条随机连线:

const graph = new Graph({ layout: { type: 'grid', cols: 5, rows: 5, }, data: { nodes: Array.from({ length: 25 }, (_, i) => ({ id: `node-${i}`, data: { value: Math.random() * 100, }, })), edges: Array.from({ length: 20 }, (_, i) => ({ id: `edge-${i}`, source: `node-${Math.floor(Math.random() * 25)}`, target: `node-${Math.floor(Math.random() * 25)}`, })), }, });

一个可运行的完整示例(带容器与渲染调用):

import { Graph } from '@antv/g6'; const graph = new Graph({ container: 'container', width: 600, height: 400, layout: { type: 'grid', cols: 5, rows: 5, }, data: { nodes: Array.from({ length: 25 }, (_, i) => ({ id: `node-${i}`, data: { value: Math.random() * 100 }, })), edges: Array.from({ length: 20 }, (_, i) => ({ id: `edge-${i}`, source: `node-${Math.floor(Math.random() * 25)}`, target: `node-${Math.floor(Math.random() * 25)}`, })), }, node: { style: { size: 20, label: true, labelText: (datum) => datum.id, labelBackground: true, }, }, edge: { style: { stroke: '#bfbfbf', }, }, }); graph.render();

说明:节点数据里塞入data.value等自定义字段,可以为后续的sortBy排序、palette分组着色等能力做准备。

配置项详解:每个参数的行为与默认值

Grid 布局的完整配置在 GridLayout.en.md 中以表格形式给出,下面逐项展开说明。

标准配置写法

const graph = new Graph({ layout: { type: 'grid', begin: [0, 0], cols: 5, rows: 5, width: 300, height: 300, preventOverlap: true, nodeSize: 30, condense: false, }, });

参数总表

PropertyDescriptionTypeDefaultRequired
type布局类型grid-
begin网格起始位置(左上角坐标),默认[0, 0][number, number][0, 0]
cols列数。若未定义,算法会根据节点数量、布局空间及 rows(若设置)自动计算numberundefined
rows行数。若未定义,算法会根据节点数量、布局空间及 cols(若设置)自动计算number10
width布局区域宽度。在 G6 中默认使用容器宽度number300
height布局区域高度。在 G6 中默认使用容器高度number300
condensefalse 时使用全部可用画布空间;true 时使用最小画布空间booleanfalse
nodeSize节点尺寸(直径),用于防重叠时的碰撞检测Size | ((nodeData: Node) => Size)-
nodeSpacing节点间距,用于调整节点之间的空隙((node?: Node) => number) | number-
position为每个节点指定所在行列(node?: Node) => { row?: number; col?: number; }undefined
preventOverlap是否防止节点重叠。需要节点数据中存在 nodeSize 或 size 属性booleanfalse
preventOverlapPadding防重叠时的内边距。仅在 preventOverlap 为 true 时生效number10
sortBy排序依据(节点属性名)。数值越大的节点越靠近中心。若未定义则按度(degree)排序stringundefined

核心参数深度解读

cols 与 rows(行列数)

两者互为补足关系:只给cols时,行数由节点总数自动推导;只给rows时,列数自动推导;都未设置时按行数为 10 的默认逻辑计算。手动指定时需确保cols * rows >= 节点数,否则多余节点会被截断到网格范围之外。官方在线 Demo 提供了 2~10 的调节范围(GridLayout.en.md)。

width 与 height(布局区域)

决定网格可铺陈的空间。需要注意:官方文档特别注明,在 G6 中布局宽度默认使用容器宽度;而当 Grid 布局单独使用(未接容器)时默认值为 300。从源码看,width/height同样被声明在BaseLayoutOptions中,默认取画布尺寸(packages/g6/src/layouts/types.ts#L86-L96)。

condense(紧凑模式)

  • false(默认):网格占满整个可用布局空间,节点之间的间距会被均匀拉大,视觉上更松散;
  • true:按最小必要空间排布,节点紧凑靠拢,适合节点数量多、画布有限的情况。

nodeSize 与 nodeSpacing(尺寸与间距)

  • nodeSize既可以是固定数字,也可以是接收节点数据、返回尺寸的函数(Size | ((nodeData) => Size));
  • nodeSpacing同样支持函数或数字两种形式,用于在防重叠时额外拉开间隙;
  • 两者共同参与防重叠算法中的碰撞检测与位置微调。

preventOverlap 与 preventOverlapPadding(防重叠)

官方文档明确:必须配合nodeSize或节点数据中的size属性一起使用,只有数据中存在data.size或布局中设置了nodeSize,才能执行节点重叠的碰撞检测。防重叠开启后,preventOverlapPadding(默认 10)控制节点之间的内边距大小。

sortBy(排序)

指定节点属性名作为排序依据,数值越大越靠近网格中心;若未定义,则使用节点的**度(degree,即连接的边数)**作为排序依据。仓库 utils 中的注释还提到一个兼容性细节:Grid 布局会直接读取data[sortBy],因此需要避免在数据中使用datastyle等容易与内部字段冲突的属性名(packages/g6/src/utils/layout.ts#L287-L288)。

补充:Grid 布局同其他布局一样,继承了BaseLayoutOptions的通用能力,例如nodeFilter(过滤参与布局的节点)、enableWorker(是否在 Web Worker 中执行)、animation(布局动画)等,详见 packages/g6/src/layouts/types.ts#L42-L98。

进阶用法一:自定义网格与排序着色

在官方文档的 Custom Configuration 示例中,可以通过组合begincolsrowswidthheightcondensesortBy精细控制网格形态,并配合节点palette做分组着色:

const graph = new Graph({ layout: { type: 'grid', begin: [50, 50], // 从 [50, 50] 开始排布 cols: 4, // 4 列 rows: 6, // 6 行 width: 400, // 布局区域宽度 height: 600, // 布局区域高度 preventOverlap: true, // 防止节点重叠 nodeSize: 30, // 节点尺寸 condense: true, // 使用最小空间 sortBy: 'value', // 按 value 属性排序 }, data: { nodes: Array.from({ length: 24 }, (_, i) => ({ id: `node-${i}`, data: { value: Math.random() * 100, // 排序依据属性 }, })), edges: Array.from({ length: 20 }, (_, i) => ({ id: `edge-${i}`, source: `node-${Math.floor(Math.random() * 24)}`, target: `node-${Math.floor(Math.random() * 24)}`, })), }, node: { style: { size: 20, label: true, labelText: (datum) => datum.id, labelBackground: true, }, palette: { type: 'group', field: (datum) => datum.data.value, color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'], }, }, edge: { style: { stroke: '#bfbfbf', }, }, });

要点解析:

  • begin: [50, 50]让网格整体向右下偏移,避免与画布边缘贴死;
  • sortBy: 'value'使value更大的节点落在更靠近中心的单元格;
  • palettefielddata.value分组着色,与排序协同,形成"中心高亮、外围渐变"的视觉层次;
  • condense: true在 4×6 网格中会压缩空白,使节点更紧凑。

进阶用法二:为特定节点指定行列位置

当需要"锁定"某些关键节点到固定单元格(例如四角、关键路径节点)时,使用position回调。它对返回{ row, col }的节点强制放置,返回undefined的节点则继续走自动排布:

const graph = new Graph({ layout: { type: 'grid', cols: 5, rows: 5, position: (node) => { // 为特定节点指定位置 if (node.id === 'node-0') return { row: 0, col: 0 }; // 左上角 if (node.id === 'node-1') return { row: 0, col: 4 }; // 右上角 if (node.id === 'node-2') return { row: 4, col: 0 }; // 左下角 if (node.id === 'node-3') return { row: 4, col: 4 }; // 右下角 return undefined; // 其余节点自动排布 }, }, data: { nodes: Array.from({ length: 25 }, (_, i) => ({ id: `node-${i}`, })), edges: Array.from({ length: 20 }, (_, i) => ({ id: `edge-${i}`, source: `node-${Math.floor(Math.random() * 25)}`, target: `node-${Math.floor(Math.random() * 25)}`, })), }, node: { style: { size: 20, label: true, labelText: (datum) => datum.id, labelBackground: true, }, }, edge: { style: { stroke: '#bfbfbf', }, }, }); graph.render();

注意事项:

  • row/col均从 0 开始计数;
  • 已被position占用的单元格,自动排布会跳过,不会产生节点覆盖;
  • 建议只在少量关键节点上使用,全部节点手工指定会丧失 Grid 自动布局的意义。

进阶用法三:运行时动态更新布局参数

Grid 布局并不是"一次性"的——你可以通过graph.setLayout()+graph.layout()在运行时动态调整行列数、防重叠、排序等参数并重新布局。官方在线 Demo 的交互面板即采用此模式:

const options = { type: 'grid', cols: 5, rows: 5, width: 400, height: 400, preventOverlap: true, nodeSize: 30, condense: false, }; // 修改任意参数后重新执行布局 optionFolder.onChange(({ property, value }) => { graph.setLayout({ type: 'grid', [property]: value, }); graph.layout(); });

从源码看,setLayout更新的是图实例的布局配置,layout()触发实际计算并调用model.updateData()把结果写回节点坐标(packages/g6/src/runtime/layout.ts)。这一能力让"用户拖拽调节滑块、图实时重排"成为可能,非常适合配置面板、可视化编辑器类产品。

仓库中的实证:Demo 与单元测试

仓库内置了 Grid 布局的完整示例与测试,可直接作为参考或运行验证:

  • 交互示例:layout-grid.ts 使用cluster.json数据集,演示了默认sortBy按度排序,以及通过面板在iddegreecluster三种排序策略间切换:
export const layoutGrid: TestCase = async (context) => { const graph = new Graph({ ...context, data, node: { style: { labelText: (d) => d.id } }, layout: { type: 'grid', sortBy: (d) => d.data.cluster, }, behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element', 'click-select'], }); await graph.render(); // ... };
  • 单元测试:grid.spec.ts 覆盖了sortBy默认行为与sortBy: 'id'两种场景的 SVG 快照断言:
describe('grid', () => { it('sortBy default', async () => { await expect(graph).toMatchSnapshot(__filename, 'sortby-default'); }); it('sortBy id', async () => { graph.setLayout({ type: 'grid', sortBy: 'id' }); await graph.layout(); await expect(graph).toMatchSnapshot(__filename, 'sortby-id'); }); });
  • 多布局流水线:pipeline.spec.ts 中还验证了 Grid 可作为layout: [...]数组流水线中的一环,说明它能与 dagre 等其他布局串联使用。

  • 真实用例:官方示例站点的 Grid Layout 基础示例 提供了开箱即用的演示代码。

常见问题与最佳实践

Q1:节点重叠了怎么办?

确保两件事同时满足:布局中设置nodeSize(或节点数据带size),并开启preventOverlap: true。还可配合preventOverlapPadding增加间隙、nodeSpacing拉开间距。

Q2:行列数怎么选?

规则明确:cols * rows >= 节点数即可铺满。若节点数动态变化,建议只给cols(或只给rows),让算法自动推导另一维,避免出现空行空列。

Q3:想让重点节点居中?

sortBy指定数值型属性,数值越大越靠中心;无属性时默认按节点度排序,即"连接越多的节点越居中"。

Q4:与力导向等布局混用?

Grid 是非迭代布局,一次计算完成。在多布局流水线(layout: [grid, force])中通常放在靠前阶段做初排,后续布局再做精排。

最佳实践小结

  1. 纯表格陈列用condense: true压缩空间;需要呼吸感用condense: false
  2. 节点尺寸不统一时,nodeSize传函数按节点返回尺寸,防重叠更准确;
  3. 排序字段避免与内部保留字段(datastyle等)重名;
  4. 交互式调参场景使用setLayout + layout()组合,实时反馈。

总结

Grid 布局是 G6 中"秩序感"最强的布局方案:通过cols/rows控制网格密度,begin/width/height控制铺陈区域,preventOverlap/nodeSize/nodeSpacing保证不重叠,sortBy实现数值中心化排序,position实现定点放置,再配合setLayout()动态重排,可以胜任从静态矩阵表到交互式配置面板的各类规整排版需求。官方文档详见 GridLayout.en.md,源码入口见 packages/g6/src/layouts/types.ts 与 packages/g6/src/registry/build-in.ts#L166。

  • 数据可视化
  • 前端
  • 图表库

【免费下载链接】G6

♾ A Graph Visualization Framework in JavaScript.

项目地址:https://gitcode.com/gh_mirrors/g6/G6
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询