集成第三方布局算法
relation-graph 可以和 d3-force、dagre、elkjs 等第三方布局器配合使用。
1. 集成原则
第三方算法负责在外部计算节点坐标。
然后通过实例 API 回写到图谱:
graphInstance.updateNodePosition(nodeId, x, y)
注意:第三方布局不会由 setJsonData、doLayout、createLayout 自动触发。
2. 标准接入流程
- 从实例读取节点和连线(
getNodes、getLines)。 - 构造第三方算法输入模型。
- 执行算法得到坐标。
- 用
updateNodePosition回写坐标。 - 按需调用
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 一致。
- 回写坐标后,仅在需要时再执行居中/缩放。
- 交互式编辑器中避免每次小改动都全量重排,建议批处理。
- 外部算法假设的节点宽高应尽量与真实渲染尺寸一致。