正交折线标签控制
这是一个用于调优正交树连线分离标签的紧凑 relation-graph 示例。它将同一棵树旋转为四个方向,批量更新在线连线的标签位置与锚点,并提供偏移、折点距离和圆角半径控制以对比可读性。
正交连线标签控制
这个示例构建了什么
这个示例构建了一个紧凑的树形布局实验环境,用于演示正交连接线上的分离式文本标签。画布展示了一棵固定的示例树,节点标签为纯黑色,连线标签为蓝色;同时,一个悬浮的工具窗口允许用户旋转树的方向、调整连线文本的位置、切换文本锚点,并微调标签偏移和折线几何。其主要结果是:当相同的关系通过不同的正交方向重新布线时,用户可以并排对比标签的可读性。
数据是如何组织的
图数据是一个内联的 RGJsonData 对象,包含一个 rootId、一个扁平的 nodes 数组,以及一个定义树边的 lines 数组。在调用 setJsonData 之前没有 fetch 步骤,也没有领域特定的预处理;组件直接加载准备好的示例数据,然后执行布局。在真实应用中,相同的数据结构可以表示审批链、分类树、调用层级、依赖树,或任何需要可读边标签的父子关系。
relation-graph 是如何使用的
index.tsx 使用 RGProvider 包裹整个示例,MyGraph.tsx 则通过 RGHooks.useGraphInstance() 来控制数据加载、重新布局、视口适配和连线更新。RelationGraph 实例接收一个树布局配置,其中包含 RGLineShape.SimpleOrthogonal、defaultLineTextOnPath: false、与方向相关的 defaultJunctionPoint、由状态驱动的文本偏移,以及由状态驱动的默认折线圆角半径。当方向选择器变化时,示例会调用 graphInstance.updateOptions(...) 来切换 layout.from、layoutDirection 以及水平或垂直节点间距,然后重新执行 doLayout()、moveToCenter() 和 zoomToFit()。
标签控制有意使用了两种不同的机制。defaultLineTextOffsetX、defaultLineTextOffsetY 和 defaultPolyLineRadius 通过图配置项传入,而 placeText、textAnchor 和 polyLineStartDistance 则通过 getLines() 与 updateLine() 以命令式方式应用到每一条现有连线上。页面没有使用自定义节点、连线或画布插槽;它依赖的是图配置项、实例 API、一个悬浮辅助组件以及样式表覆盖。共享的 DraggableWindow 还提供了一个设置浮层,用户可以在其中调整滚轮模式、切换拖拽行为,并将当前图导出为图片。
关键交互
- 方向选择器可在
left、right、top和bottom之间切换树方向,然后重新计算布局,从而在水平和垂直方向中对比同一组标签。 Place Text和Line Text Anchor选择器会批量更新当前所有边,在不重建数据集的情况下改变标签语义。- x-offset 和 y-offset 滑块会将新的默认标签偏移传入图配置,使分离式标签沿正交线段移动。
- first-bend 滑块会修改每条活动边上的
polyLineStartDistance,radius 滑块则会修改正交拐角的默认圆角半径。 - 悬浮工具窗口可以拖动或最小化,其设置面板还可以切换滚轮或拖拽行为,并下载当前图像。
关键代码片段
这段配置将示例固定为正交路由,并把标签偏移、分离式文本和折线圆角半径接入 relation-graph 配置。
const graphOptions: RGOptions = {
debug: false,
defaultNodeWidth: 70,
defaultNodeHeight: 30,
defaultLineWidth: 2,
defaultLineShape: RGLineShape.SimpleOrthogonal,
defaultJunctionPoint: (layoutFrom === 'left' || layoutFrom === 'right') ? RGJunctionPoint.lr : RGJunctionPoint.tb,
defaultLineTextOnPath: false,
defaultLineTextOffsetX: textOffsetX,
defaultLineTextOffsetY: textOffsetY,
defaultPolyLineRadius: defaultPolyLineRadius,
这段分支展示了示例如何在要求图重新布局之前,切换方向和间距规则。
const updateMyOptions = () => {
const layoutOptions = graphOptions.layout as RGTreeLayoutOptions;
if (layoutFrom === 'left' || layoutFrom === 'right') {
graphInstance.updateOptions({
layout: {
...layoutOptions,
from: layoutFrom,
treeNodeGapH: 200,
treeNodeGapV: 10,
layoutDirection: 'h'
}
});
这个函数是连线级变更的核心模式:它会重写每条当前边上的文本放置方式、锚点和首段折点距离。
const updateTextPlacementAndAnchor = () => {
for (const line of graphInstance.getLines()) {
graphInstance.updateLine(line, {
placeText,
textAnchor,
polyLineStartDistance
});
}
};
这段导出流程来自共享的悬浮设置面板,展示了如何为图 DOM 的图片捕获做准备。
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');
}
这个示例的独特之处
根据对比数据,这个示例并不只是另一个连线标签示例。与 line-text-position 相比,它将连线形状固定为 SimpleOrthogonal,重点始终放在分离式正交标签语义上,而不是在不同形状族或沿路径文本模式之间切换。与 text-on-curve 相比,它关注的是折线拐点周围的离线路径可读性,而不是曲线路径文本或截断。与 adv-line-slot3 和 ever-changing-tree 相比,它更强调连线级的放置逻辑,因为它在一个更小、更诊断型的界面中组合了 placeText、textAnchor、polyLineStartDistance、与方向相关的重新布局,以及圆角半径调节。
对比记录还强调了一个不太常见的组合:一个极简的正交树、蓝色强调的分离式标签、四向切换、逐线的放置和锚点重写、首段折点控制,以及同一悬浮面板中的图级偏移和圆角控制。这使得该示例更适合作为标签可读性工作的起点,而不是通用连线样式或图编辑功能的起点。
这种模式还能应用到哪里
这种模式很适合迁移到那些在布局方向改变后仍需保持边标签可读性的树形界面中。例如,带有角色注释的组织架构图、带决策标签的审批树、带协议或归属文本的服务依赖树、带边语义的菜单或分类浏览器,以及需要打印或导出截图的工作流树。其可复用的核心思想是:保持数据稳定,同时暴露图级默认值和逐线覆盖能力,这样团队就可以在最终确定视觉语言之前,先对标签可读性进行调优。