|
| 1 | +import { DagreLayout, type DagreLayoutOptions } from '@antv/layout' |
| 2 | + |
| 3 | +export default class Dagre { |
| 4 | + static pluginName = 'dagre' |
| 5 | + lf: any |
| 6 | + option: DagreLayoutOptions | any |
| 7 | + render(lf: any) { |
| 8 | + this.lf = lf |
| 9 | + } |
| 10 | + |
| 11 | + /** |
| 12 | + * option: { |
| 13 | + * rankdir: "TB", // layout 方向, 可选 TB, BT, LR, RL |
| 14 | + * align: undefined, // 节点对齐方式,可选 UL, UR, DL, DR |
| 15 | + * nodeSize: undefined, // 节点大小 |
| 16 | + * nodesepFunc: undefined, // 节点水平间距(px) |
| 17 | + * ranksepFunc: undefined, // 每一层节点之间间距 |
| 18 | + * nodesep: 40, // 节点水平间距(px) 注意:如果有grid,需要保证nodesep为grid的偶数倍 |
| 19 | + * ranksep: 40, // 每一层节点之间间距 注意:如果有grid,需要保证ranksep为grid的偶数倍 |
| 20 | + * controlPoints: false, // 是否保留布局连线的控制点 |
| 21 | + * radial: false, // 是否基于 dagre 进行辐射布局 |
| 22 | + * focusNode: null, // radial 为 true 时生效,关注的节点 |
| 23 | + * }; |
| 24 | + */ |
| 25 | + layout(option = {}) { |
| 26 | + const { nodes, edges, gridSize } = this.lf.graphModel |
| 27 | + // 为了保证生成的节点在girdSize上,需要处理一下。 |
| 28 | + let nodesep = 40 |
| 29 | + let ranksep = 40 |
| 30 | + if (gridSize > 20) { |
| 31 | + nodesep = gridSize * 2 |
| 32 | + ranksep = gridSize * 2 |
| 33 | + } |
| 34 | + this.option = { |
| 35 | + type: 'dagre', |
| 36 | + rankdir: 'LR', |
| 37 | + // align: 'UL', |
| 38 | + // align: 'UR', |
| 39 | + align: 'DR', |
| 40 | + nodesep, |
| 41 | + ranksep, |
| 42 | + begin: [120, 120], |
| 43 | + ...option |
| 44 | + } |
| 45 | + const layoutInstance = new DagreLayout(this.option) |
| 46 | + const layoutData = layoutInstance.layout({ |
| 47 | + nodes: nodes.map((node: any) => ({ |
| 48 | + id: node.id, |
| 49 | + size: { |
| 50 | + width: node.width, |
| 51 | + height: node.height |
| 52 | + }, |
| 53 | + model: node |
| 54 | + })), |
| 55 | + edges: edges.map((edge: any) => ({ |
| 56 | + source: edge.sourceNodeId, |
| 57 | + target: edge.targetNodeId, |
| 58 | + model: edge |
| 59 | + })) |
| 60 | + }) |
| 61 | + |
| 62 | + layoutData.nodes?.forEach((node: any) => { |
| 63 | + // @ts-ignore: pass node data |
| 64 | + const { model } = node |
| 65 | + model.set_position({ x: node.x, y: node.y }) |
| 66 | + }) |
| 67 | + this.lf.fitView() |
| 68 | + } |
| 69 | +} |
0 commit comments