ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

X6 网格(Grid)完全指南:最小对齐单位、四种内置网格与自定义实现

X6 网格(Grid)完全指南:最小对齐单位、四种内置网格与自定义实现 X6 网格Grid完全指南最小对齐单位、四种内置网格与自定义实现【免费下载链接】X6 JavaScript diagramming library that uses SVG and HTML for rendering.项目地址: https://gitcode.com/GitHub_Trending/x6/X6网格Grid是 X6 图编辑器中用于对齐节点渲染与移动的最小度量单位。本篇指南以site/docs/api/graph/grid.en.md为基础结合 src/graph/grid.ts、src/registry/grid 等源码与测试用例系统讲解网格的配置方式size、type、args、getGridSize/setGridSize/showGrid/hideGrid/clearGrid/drawGrid等运行时 API以及通过Graph.registerGrid自定义网格的实现原理帮助你完成从基础对齐到高级定制的完整落地。网格是什么渲染与移动的最小单位网格是 X6 画布中渲染/移动节点的最小单位默认大小为10px。它同时影响两个维度渲染对齐节点渲染时按网格对齐以10为最小单位取整。例如位置为{ x: 24, y: 38 }的节点会被渲染到画布上的{ x: 20, y: 40 }。移动步进拖动节点时每次移动的最小距离为10px。该行为由 GridManager 统一管理其默认值定义在 src/graph/options.ts 中const defaultGrid: GridCommonOptions { size: 10, visible: false }即默认网格大小为 10px且默认不可见visible: false。网格可见性只影响视觉绘制不影响对齐逻辑——即使不显示网格渲染与移动依然按size对齐。基础配置size 与可见性size设置网格尺寸创建画布时可通过grid选项设置网格尺寸支持简写数字形式与完整对象形式const graph new Graph({ grid: 10, }) // 等价于 const graph new Graph({ grid: { size: 10, }, })从 src/graph/options.ts 的配置归一化逻辑可以看到grid选项支持三种写法if (typeof grid number) { result.grid { size: grid, visible: false } } else if (typeof grid boolean) { result.grid { ...defaultGrid, visible: grid } } else { result.grid { ...defaultGrid, ...grid } }数字如10等价于{ size: 10, visible: false }布尔值true/false使用默认尺寸 10仅切换可见性对象size、visible、type、args等字段与默认值深度合并。需要说明的是setGridSize对尺寸有下限保护在 GridManager.setGridSize 中执行Math.max(size, 1)即最小网格尺寸为 1px而update()中当gridSize 1时网格会直接清空不绘制src/graph/grid.ts。显示网格网格默认不可见可通过配置在创建时开启绘制const graph new Graph({ grid: true, // Grid size is 10px and draw the grid }) // 等价于 const graph new Graph({ grid: { size: 10, // Grid size is 10px visible: true, // Draw the grid, default is dot type }, })当visible: true且未指定type时默认绘制dot点状网格。四种内置网格类型X6 内置了四种网格类型通过type选项指定默认值为dot同时可通过args选项配置网格样式。四种类型分别定义于 src/registry/grid 目录下的dot.ts、fixed-dot.ts、mesh.ts、double-mesh.ts统一注册在 src/registry/grid/index.ts。dot默认点状网格用圆角矩形rect绘制网格点new Graph({ container: this.container, grid: { visible: true, type: dot, args: { color: #a0a0a0, // Grid point color thickness: 1, // Grid point size }, }, })源码实现src/registry/grid/dot.ts使用rect作为markup点的宽高为thickness * sx/sy随画布缩放比例缩放并以rx/ry圆角化呈现圆点效果export const dot: GridDefinitionDotOptions { color: #aaaaaa, thickness: 1, markup: rect, update(elem, options) { const width options.thickness * options.sx const height options.thickness * options.sy Dom.attr(elem, { width, height, rx: width, ry: height, fill: options.color, }) }, }对应测试tests/registry/grid/dot.spec.ts 验证了默认属性color为#aaaaaa、thickness为 1以及不同缩放系数下宽高按thickness * sx/sy计算的行为。fixedDot固定尺寸点状网格与dot的区别在于点的大小在画布放大时保持不变当画布缩放比例小于1时点随缩放比例缩小当缩放比例大于1时点保持给定的thickness值不会随放大而变大new Graph({ container: this.container, grid: { visible: true, size: 10, type: fixedDot, args: { color: #a0a0a0, // Grid point color thickness: 2, // Grid point size }, }, }) graph.scale(10, 10)其核心逻辑在 src/registry/grid/fixed-dot.tsconst size options.sx 1 ? options.thickness * options.sx : options.thicknesssx/sy来自当前画布的缩放矩阵系数见 src/graph/grid.ts 中的ctm.a/ctm.d因此scale(10, 10)放大 10 倍后点依然保持thickness指定的物理大小。mesh网格线以线条绘制网格new Graph({ container: this.container, grid: { visible: true, type: mesh, args: { color: #ddd, // Grid line color thickness: 1, // Grid line width }, }, })实现上使用path作为markup在当前网格单元内画一条横线加一条竖线src/registry/grid/mesh.tsif (width - thickness 0 height - thickness 0) { d [M, width, 0, H0 M0 0 V0, height].join( ) } else { d M 0 0 0 0 } Dom.attr(elem, { d, stroke: options.color, stroke-width: options.thickness, })当网格单元尺寸小于线宽时路径退化为M 0 0 0 0空路径避免绘制异常。doubleMesh双层网格由主网格线与次网格线叠加组成args为两个配置对象组成的数组const graph new Graph({ grid: { size: 10, visible: true, type: doubleMesh, args: [ { color: #eee, // Main grid line color thickness: 1, // Main grid line width }, { color: #ddd, // Secondary grid line color thickness: 1, // Secondary grid line width factor: 4, // Main and secondary grid line interval }, ], }, })doubleMesh在注册表中对应一个网格定义数组src/registry/grid/double-mesh.ts由两层组成第一层基础网格线线宽由thickness决定第二层次网格线线宽与颜色独立并通过factor默认 4控制间隔——第二层实际绘制区域的宽高为options.width * factor、options.height * factor形成每 4 个基础格出现一条加粗/深色主线的效果。在 GridManager.resolveGrid 中args会被统一为数组再按下标与网格定义一一合并这正是doubleMesh支持args数组的原因。运行时方法动态控制网格X6 的Graph实例将网格管理方法代理至GridManager见 src/graph/graph.ts全部返回this支持链式调用。getGridSize()获取当前网格尺寸getGridSize(): number内部实现直接返回this.grid.sizesrc/graph/grid.ts。setGridSize()设置网格尺寸注意下限为 1setGridSize(gridSize: number): this// 实际执行 setGridSize(size: number) { this.grid.size Math.max(size, 1) this.update() }showGrid() / hideGrid()显示/隐藏网格showGrid(): this hideGrid(): this两者都会修改grid.visible并触发update()重绘src/graph/grid.ts。clearGrid()清空网格背景clearGrid(): this实现为清空画布元素的backgroundImage样式src/graph/grid.ts。drawGrid(...)按给定参数重绘网格drawGrid(options?: DrawGridOptions): this参数说明NameTypeRequiredDefaultDescriptiontypestringdot网格类型详见 网格注册表文档argsobject-与网格类型对应的网格参数从实现上看src/graph/grid.tsdrawGrid会先清空旧网格、重置实例将传入的 options 合并进当前this.grid再重新解析网格定义并更新绘制。缩放与平移时的自动重绘网格绘制会跟随画布的scale与translate事件自动更新。GridManager在初始化时注册监听src/graph/grid.tsprotected startListening() { this.graph.on(scale, this.update, this) this.graph.on(translate, this.update, this) }每次更新时网格会读取当前画布变换矩阵ctm.a/ctm.d/ctm.e/ctm.f将其作为sx/sy/ox/oy传给网格定义的update函数同时计算 pattern 的偏移x ox % width、y oy % height负数时回绕取正保证平移时网格线与背景贴合src/graph/grid.ts。绘制完成后整个 SVG pattern 会被序列化为data:image/svgxml;base64,...的 Data URL写入画布元素的backgroundImagesrc/graph/grid.ts即网格本质上是画布的一层背景图案。自定义网格registerGrid除了四种内置类型还可以通过Graph.registerGrid注册自定义网格。每个网格定义需要包含color、thickness、markupSVG 元素名以及update(elem, options)更新函数。下面注册一个红色点状网格Graph.registerGrid(red-dot, { color: red, thickness: 1, markup: rect, update(elem, options) { const width options.thickness * options.sx const height options.thickness * options.sy Dom.attr(elem, { width, height, rx: width, ry: height, fill: options.color, }) }, }) const graph new Graph({ grid: { type: red-dot, }, })注册后的类型可直接通过grid.type使用。update函数接收的options除自定义字段如color、thickness外还包括由网格管理器注入的运行时参数见 src/registry/grid/index.tssx/sy当前画布 X/Y 方向的缩放比例ox/oy当前画布平移偏移width/height单个网格单元的绘制尺寸gridSize * sx等。这也解释了为何自定义网格的示例中要用thickness * sx计算宽高——只有这样才能保证点的大小随画布缩放同步变化原理与内置dot完全一致。registerGrid底层基于 X6 的通用注册表机制Registry.create({ type: grid })见 src/registry/grid/index.ts与节点、边等其他注册表共用同一套注册/查找/未命中处理流程。当传入的type在注册表中不存在时会走gridRegistry.onNotFound(type)兜底src/graph/grid.ts。小结网格是 X6 画布对齐体系的基础设施size决定对齐与移动的最小单位visible/type/args决定背景的呈现样式showGrid/hideGrid/clearGrid/drawGrid与getGridSize/setGridSize提供运行时控制而Graph.registerGrid与update(elem, options)的注入参数sx/sy/ox/oy/width/height则让开发者可以完全自定义网格的视觉形态。结合 源码实现 与 内置网格定义 阅读可以更深入地理解网格在缩放、平移场景下的重绘原理并将其灵活应用到实际图编辑场景中。【免费下载链接】X6 JavaScript diagramming library that uses SVG and HTML for rendering.项目地址: https://gitcode.com/GitHub_Trending/x6/X6创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表