JavaScript is required

关联对象数据(RGLink

RGLink 是 relation-graph 在运行时根据连线和节点自动计算出来的“关系上下文对象”。它不是你输入的数据,而是图谱内部把 RGLine 与两端 RGNode 关联之后得到的派生对象。

一句话理解:

  • RGLine 保存“这条线本身是什么”。
  • RGNode 保存“节点本身是什么”。
  • RGLink 保存“这条线连接了哪两个节点,以及这条连接在运行时应如何参与渲染/分析”。

1. RGLinkRGLine 的区别

对比项 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.hidden
  • fromNode.rgCalcedVisibility
  • toNode.rgCalcedVisibility
  • 父节点折叠导致的后代隐藏
  • 数据提供者的可见性刷新

典型判断:

const link = graphInstance.getLinkByLineId('line-a-b');

if (link?.rgCalcedVisibility) {
  // 当前关系在图上应当可见
}

rgShouldRender

表示当前 link 是否应该实际进入渲染。它更偏向性能和视口裁剪结果,不等同于业务上的“存在”或“可见”。

实践建议:

  • 判断业务关系是否存在:查 linelink
  • 判断当前是否可见:优先看 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 后界面没有稳定更新?

不要直接改运行时对象。请使用 updateLineupdateLineDataupdateNode 等实例 API,让数据提供者触发状态刷新和关系重算。

11. 下一步阅读