JavaScript is required

集成第三方布局算法

relation-graph 可以和 d3-forcedagreelkjs 等第三方布局器配合使用。

1. 集成原则

第三方算法负责在外部计算节点坐标。

然后通过实例 API 回写到图谱:

  • graphInstance.updateNodePosition(nodeId, x, y)

注意:第三方布局不会由 setJsonDatadoLayoutcreateLayout 自动触发。

2. 标准接入流程

  1. 从实例读取节点和连线(getNodesgetLines)。
  2. 构造第三方算法输入模型。
  3. 执行算法得到坐标。
  4. updateNodePosition 回写坐标。
  5. 按需调用 moveToCenter / zoomToFit

3. d3-force 示例

import * as d3 from 'd3-force';

async function applyD3ForceLayout(graphInstance) {
  const nodes = graphInstance.getNodes().map(n => ({ id: n.id }));
  const links = graphInstance.getLines().map(l => ({ source: l.from, target: l.to }));

  const simulation = d3.forceSimulation(nodes)
    .force('link', d3.forceLink(links).id(d => d.id).distance(100))
    .force('charge', d3.forceManyBody().strength(-200))
    .force('center', d3.forceCenter(0, 0));

  return new Promise(resolve => {
    simulation.on('end', () => {
      nodes.forEach(d => graphInstance.updateNodePosition(d.id, d.x, d.y));
      resolve(undefined);
    });
  });
}

4. dagre 示例

import * as dagre from 'dagre';

async function applyDagreLayout(graphInstance) {
  const g = new dagre.graphlib.Graph();
  g.setGraph({});
  g.setDefaultEdgeLabel(() => ({}));

  graphInstance.getNodes().forEach(node => g.setNode(node.id, { width: 100, height: 50 }));
  graphInstance.getLines().forEach(line => g.setEdge(line.from, line.to));

  dagre.layout(g);
  g.nodes().forEach(nodeId => {
    const node = g.node(nodeId);
    graphInstance.updateNodePosition(nodeId, node.x, node.y);
  });
}

5. elkjs 示例

import ELK from 'elkjs/lib/elk.bundled.js';

async function applyElkLayout(graphInstance) {
  const elk = new ELK();
  const elkGraph = {
    id: 'root',
    layoutOptions: { 'elk.algorithm': 'layered' },
    children: graphInstance.getNodes().map(n => ({ id: n.id, width: 100, height: 50 })),
    edges: graphInstance.getLines().map(l => ({ id: `${l.from}-${l.to}`, source: l.from, target: l.to }))
  };

  const layout = await elk.layout(elkGraph);
  layout.children.forEach(node => {
    graphInstance.updateNodePosition(node.id, node.x, node.y);
  });
}

6. 实践建议

  • 外部布局模型中的节点 id 必须与图谱节点 id 一致。
  • 回写坐标后,仅在需要时再执行居中/缩放。
  • 交互式编辑器中避免每次小改动都全量重排,建议批处理。
  • 外部算法假设的节点宽高应尽量与真实渲染尺寸一致。

7. 下一步阅读