关联对象数据(RGLink)
RGLink 是 relation-graph 在运行时根据连线和节点自动计算出来的“关系上下文对象”。它不是你输入的数据,而是图谱内部把 RGLine 与两端 RGNode 关联之后得到的派生对象。
一句话理解:
RGLine保存“这条线本身是什么”。RGNode保存“节点本身是什么”。RGLink保存“这条线连接了哪两个节点,以及这条连接在运行时应如何参与渲染/分析”。
1. RGLink 与 RGLine 的区别
| 对比项 | RGLine |
RGLink |
|---|---|---|
| 来源 | 由 JsonLine 转换而来 |
根据 RGLine 和节点索引自动计算 |
| 是否由用户创建 | 是,用户通过 lines / addLines 提供 |
否,运行时自动生成 |
| 是否适合持久化 | 是 | 否 |
| 是否包含端点节点对象 | 否,只包含 from/to id |
是,包含 fromNode/toNode |
| 是否包含多线索引 | 否 | 是,包含 totalLinesBetweenNodes/currentLineIndex |
| 是否可直接修改 | 可通过 updateLine 修改 |
不应直接修改 |
2. 获取 RGLink
const links = graphInstance.getLinks();
const link = graphInstance.getLinkByLineId('line-a-b');
在连线事件中也会直接拿到:
const onLineClick = (line, link, event) => {
console.log(line.id);
console.log(link.fromNode.id, link.toNode.id);
};
注意:
getLinks()返回普通连线对应的RGLink[]。- FakeLine 通常不在
getLinks()的普通结果中;部分内部分析逻辑会把可解析回节点的 FakeLine 临时转成类似 link 的上下文。 getLinkByLineId(id)面向普通连线 id。
3. 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
lineId |
string |
对应连线 id,通常等于 line.id。 |
line |
RGLine |
当前关联对象对应的运行时连线对象。修改连线时应通过 updateLine(line.id, partial)。 |
fromNode |
RGNode |
起点节点对象,对应 line.from。 |
toNode |
RGNode |
终点节点对象,对应 line.to。 |
totalLinesBetweenNodes |
number |
当前起终点节点之间的连线总数。用于多条线之间的错位计算。 |
currentLineIndex |
number |
当前线在同一节点对连线集合中的索引,从 0 开始。 |
rgShouldRender |
`boolean | undefined` |
rgCalcedVisibility |
`boolean | undefined` |
4. 多条连线中的索引含义
当同一对节点之间存在多条连线时,RGLink 会提供排序信息:
graphInstance.addLines([
{ id: 'a-b-1', from: 'a', to: 'b', text: '主链路' },
{ id: 'a-b-2', from: 'a', to: 'b', text: '备用链路' },
{ id: 'a-b-3', from: 'a', to: 'b', text: '审计链路' }
]);
const link = graphInstance.getLinkByLineId('a-b-2');
console.log(link.totalLinesBetweenNodes); // 3
console.log(link.currentLineIndex); // 例如 1
路径生成器会结合这些字段和 options.multiLineDistance 拉开多条线,避免它们完全重叠。
业务上也可以使用这些字段:
- 在属性面板中显示“第几条连接”。
- 给同一节点对之间的不同线分配不同样式。
- 自定义连线插槽时计算偏移或标签位置。
5. 可见性字段的含义
rgCalcedVisibility
表示运行时综合计算后的可见性。通常会受到这些因素影响:
line.hiddenfromNode.rgCalcedVisibilitytoNode.rgCalcedVisibility- 父节点折叠导致的后代隐藏
- 数据提供者的可见性刷新
典型判断:
const link = graphInstance.getLinkByLineId('line-a-b');
if (link?.rgCalcedVisibility) {
// 当前关系在图上应当可见
}
rgShouldRender
表示当前 link 是否应该实际进入渲染。它更偏向性能和视口裁剪结果,不等同于业务上的“存在”或“可见”。
实践建议:
- 判断业务关系是否存在:查
line或link。 - 判断当前是否可见:优先看
rgCalcedVisibility。 - 判断是否已进入当前渲染批次:再看
rgShouldRender。
6. RGLink 的正确使用场景
适合使用 RGLink 的场景:
- 连线点击事件中读取两端节点。
- 构建关系属性面板。
- 统计某节点对之间有多少条连线。
- 自定义连线渲染时读取
currentLineIndex。 - 做运行时图分析,例如查找某组节点之间的连线。
示例:点击连线后显示端点信息。
const onLineClick = (line, link) => {
inspector.value = {
lineId: link.lineId,
from: {
id: link.fromNode.id,
text: link.fromNode.text
},
to: {
id: link.toNode.id,
text: link.toNode.text
},
index: link.currentLineIndex,
total: link.totalLinesBetweenNodes
};
};
7. 不要把 RGLink 当成可写数据
错误做法:
const link = graphInstance.getLinkByLineId('line-a-b');
link.fromNode = anotherNode; // 不要这样做
link.totalLinesBetweenNodes = 99; // 不要这样做
正确做法:
// 修改连线文本、样式或业务数据
graphInstance.updateLine('line-a-b', {
text: '新的关系',
color: '#2563eb'
});
// 修改节点属性
graphInstance.updateNode('a', {
text: '新的节点名称'
});
// 改变关系端点:建议删除旧线后新增新线
graphInstance.removeLineById('line-a-b');
graphInstance.addLines([
{
id: 'line-a-c',
from: 'a',
to: 'c',
text: '新的关系'
}
]);
8. 关系分析 API 中的 RGLink
常用关系查询:
const node = graphInstance.getNodeById('a');
const relatedLines = graphInstance.getRelatedLinesByNode(node);
const relatedNodes = graphInstance.getNodeRelatedNodes(node);
const incomingNodes = graphInstance.getNodeIncomingNodes(node);
const outgoingNodes = graphInstance.getNodeOutgoingNodes(node);
const networkNodes = graphInstance.getNetworkNodesByNode(node);
const linksBetween = graphInstance.getLinksBetweenNodes([nodeA, nodeB, nodeC]);
const linesBetween = graphInstance.getLinesBetweenNodes([nodeA, nodeB, nodeC]);
几个边界:
getNodeRelatedNodes(node)默认同时包含入向和出向节点。- 可以通过
{ incoming: true/false, outgoing: true/false }控制方向。 forDisplayOnly的线会在部分关系分析中被跳过。- 可解析回节点的 FakeLine 可能参与部分关系分析;HTML 元素或纯自定义目标不要默认当作普通结构关系。
9. 导出与持久化
持久化时不要保存 RGLink。推荐:
const jsonData = graphInstance.getGraphJsonData();
或按需转换:
const link = graphInstance.getLinkByLineId('line-a-b');
if (link) {
const lineJson = graphInstance.transRGLinkToJsonObject(link);
const effectiveLineJson = graphInstance.transRGLinkToJsonObject(link, {
mode: 'effective'
});
}
mode: 'compact' 与 mode: 'effective' 的区别:
- 默认紧凑模式会尽量省略默认值和运行时字段。
effective会把全局默认值解析进结果,例如默认线色、默认线宽、默认连接点等,适合调试和生成完整配置快照。
10. 常见问题
为什么 getLinkByLineId 返回空?
常见原因:
- 传入的是 FakeLine id。
- 普通线创建失败,例如
from/to节点不存在。 - 连线 id 重复导致新增时被跳过。
- 图谱数据还未加载完成。
为什么 line.hidden 是 false,但 link 不可见?
因为 link 可见性还会参考两端节点。如果节点被隐藏、父级折叠或运行时可见性未刷新,rgCalcedVisibility 仍可能为 false。
为什么修改 link.line 后界面没有稳定更新?
不要直接改运行时对象。请使用 updateLine、updateLineData、updateNode 等实例 API,让数据提供者触发状态刷新和关系重算。