树布局与连线参数调节
这个示例把固定树数据集变成 relation-graph 的实时调参工作台。用户可调整树方向与间距、批量重设现有连线样式、切换画布交互模式,并在不重建数据的情况下导出当前视图为图片。
通过实时布局与连线控制微调树形图
这个示例构建了什么
这个示例围绕一份预先准备好的层级数据,构建了一个全高度的树形布局交互调试场景。画布中展示的是一棵紧凑的单色蓝色树,带有盒状的连线标签、位于底部居中的内置工具栏,以及悬浮在图上方的白色控制窗口。
用户可以切换树的朝向、调整水平和垂直间距、重新设置所有已渲染连线的样式、移动连线标签偏移、修改滚轮和拖拽行为,并将当前画布导出为图片。这个示例的重点不是数据编辑,而是在已加载的图实例上进行实时展示调优。
数据是如何组织的
图数据以内联方式声明为一个 RGJsonData 对象,包含 rootId、扁平的 nodes 数组和扁平的 lines 数组。每个节点只使用简单的 id 和 text,每条连线使用 id、text、from 和 to。这样可以让示例聚焦于布局与样式行为,而不是特定业务领域的内容。
在调用 setJsonData() 之前没有预处理步骤。initializeGraph() 会直接加载这份准备好的树数据,然后执行居中与适配。另有一个单独的 React 状态对象保存用于驱动运行时行为的控制值:layoutFrom、rangeHorizontal、rangeVertical、lineShape、junctionPoint、lineRadius、textOffsetX 和 textOffsetY。
在真实项目中,相同的数据结构可以表示组织架构图、产品分类树、依赖树或导航层级。这个控制状态对象也可以来自用户偏好、预设选择器或管理后台的调优面板。
relation-graph 是如何使用的
index.tsx 使用 RGProvider 包裹整个演示,因此子组件可以通过 hooks 访问当前活动的图实例。RelationGraph 以一组图级默认配置进行渲染,使示例在视觉上保持稳定:树形布局、节点和连线共享同一种蓝色、60 x 60 的节点方框,以及位于底部居中的水平工具栏。
主示例组件使用 RGHooks.useGraphInstance() 处理所有图相关操作。它会在初始化时调用一次 setJsonData(),随后在方向或间距控制发生变化时,通过 updateOptions({ layout }) 加上 doLayout() 重新执行布局。对于边的调优,它会通过 getLines() 读取当前已渲染的边,并对每一条边调用 updateLine(),从而在不重建数据集的情况下修改连线几何形态和标签位置。
浮动工具外壳来自 DraggableWindow。在这个共享辅助组件内部,CanvasSettingsPanel 使用 RGHooks.useGraphStore() 读取当前的 dragEventAction 和 wheelEventAction,然后通过 setOptions() 在运行时切换这些行为。这个面板还会在执行 DOM 转图片导出时,配对调用 prepareForImageGeneration() 与 restoreAfterImageGeneration()。
这个示例没有定义节点、连线、画布或视口插槽。它依赖 relation-graph 的默认渲染器,并通过 SCSS 覆盖进行定制。样式表会将节点标签设置为白色粗体,同时为连线标签添加白底和蓝色边框,使其看起来像独立的标签块。
关键交互
- 方向选择器会将
left、right、top或bottom传给layout.from,然后重新运行树布局。 - 两个范围滑块直接映射到
treeNodeGapH和treeNodeGapV,因此用户可以在不改动数据的情况下拉宽或压缩层级结构。 - 连线形状选择器会统一修改当前所有边的形状。当选择正交形状时,还会出现一个半径滑块,用于调整拐角圆角。
- 连接点选择器会同时更新每条连线两端的连接点,两个偏移滑块则用于重新定位连线标签。
- 浮动窗口可以被拖动、最小化,并切换到设置叠层界面。
- 设置叠层可以将滚轮行为切换为滚动、缩放或无操作;将画布拖拽行为切换为框选、移动或无操作;并将图导出为图片。
关键代码片段
这段代码在任何运行时调优开始之前,先建立固定的树形布局基线和一致的视觉配色。
const graphOptions: RGOptions = {
defaultLineColor: '#2E74B5',
defaultLineWidth: 3,
defaultNodeColor: '#2E74B5',
defaultNodeWidth: 60,
defaultNodeHeight: 60,
toolBarDirection: 'h',
toolBarPositionH: 'center',
toolBarPositionV: 'bottom',
layout: {
layoutName: 'tree'
}
};
这条重新布局路径展示了如何将 React 状态转换为实时树布局选项,并应用到当前图实例。
graphInstance.updateOptions({
layout: {
layoutName: 'tree',
from: myTreeGraphOptions.layoutFrom,
treeNodeGapH: myTreeGraphOptions.rangeHorizontal,
treeNodeGapV: myTreeGraphOptions.rangeVertical
}
});
await graphInstance.doLayout();
graphInstance.moveToCenter();
graphInstance.zoomToFit();
这个循环是批量重设样式的核心模式:它读取已渲染的边,并原地逐条修改。
graphInstance.getLines().forEach((line) => {
graphInstance.updateLine(line, {
lineShape: myTreeGraphOptions.lineShape,
lineRadius: myTreeGraphOptions.lineRadius,
fromJunctionPoint: myTreeGraphOptions.junctionPoint,
toJunctionPoint: myTreeGraphOptions.junctionPoint,
textOffsetX: myTreeGraphOptions.textOffsetX,
textOffsetY: myTreeGraphOptions.textOffsetY,
placeText: (myTreeGraphOptions.lineShape === RGLineShape.StandardOrthogonal) ? 'end' : undefined
});
});
这个选择器让示例成为一个支持四个方向的树朝向调试场,而不是一个单方向查看器。
<SimpleUISelect
data={[
{ value: 'left', text: 'Left to Right' },
{ value: 'right', text: 'Right to Left' },
{ value: 'top', text: 'Top to Bottom' },
{ value: 'bottom', text: 'Bottom to Top' }
]}
currentValue={myOptions.layoutFrom}
onChange={(newValue: string) => { myOptionsUpdater({ ...myOptions, layoutFrom: newValue }); }}
/>
这个共享辅助函数表明,图片导出是通过 relation-graph 的准备与恢复 API 实现的,而不是仅仅依赖一次原始截图调用。
const canvasDom = await graphInstance.prepareForImageGeneration();
let graphBackgroundColor = graphInstance.getOptions().backgroundColor;
if (!graphBackgroundColor || graphBackgroundColor === 'transparent') {
graphBackgroundColor = '#ffffff';
}
const imageBlob = await domToImageByModernScreenshot(canvasDom, {
backgroundColor: graphBackgroundColor
});
if (imageBlob) {
downloadBlob(imageBlob, 'my-image-name');
}
await graphInstance.restoreAfterImageGeneration();
这个示例的独特之处
对比数据表明,这个示例与 tree-distance、layout-tree 和 custom-line-style 较为接近,但它强调的是另一种控制组合。它最突出的区别在于:同一个浮动面板会在同一份静态数据集上,同时控制树的重新布局参数和全图范围的连线几何属性。
- 与
tree-distance相比,这个示例不仅控制间距,还增加了四方向朝向切换和批量边几何更新。 - 与
layout-tree相比,它更像一个连续参数工作台,而不是一个精心设计的预设切换器。 - 与
custom-line-style相比,它关注的是 relation-graph 的连线属性,例如形状、连接点、圆角半径和标签偏移,而不是 CSS 皮肤样式族。 - 与
layout-folder2相比,它去除了特定业务领域的节点卡片和文件夹布局语义,从而让可复用的重点保持在树与连线 API 上。
共享的可拖拽窗口、滚轮模式切换、拖拽模式切换和图片导出都是实用的辅助功能,但对比记录并不支持把这些工具视为该示例的唯一标识。这个示例真正独特的价值,在于运行时同时控制树方向、间距和边几何属性。
这种模式还适用于哪里
- 一个组织架构图查看器,允许用户在导出演示截图之前调节层级密度和连接线样式。
- 一个分类体系或目录浏览器,不同团队可以在同一份数据上使用不同的树方向和间距预设。
- 一个依赖树或工作流树检查器,在调试过程中需要实时重新定位边标签以减少重叠。
- 一个内部调试场,用于先在代表性样本数据上测试 relation-graph 布局参数,再将产品默认值固化到代码中。