registerLayout.ts
3.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import { Base } from '@antv/layout/lib/layout/base';
import { DagreLayoutOptions, Node } from '@antv/layout/lib/layout/types';
import { itemHeight, maxLevel, nodeWidth } from './registerShape';
import G6 from '@antv/g6';
/**
* 默认从左到右(maxLayer--->minLayer)
* 默认居中对齐
*/
class CustomDagreLayout extends Base {
/** 布局的起始(左上角)位置 */
public begin: number[] = [0, 0];
/** 节点水平间距(px) */
public nodesep: number = 0;
/** 每一层节点之间间距 */
public ranksep: number = 40;
constructor(options?: DagreLayoutOptions) {
super();
this.updateCfg(options);
}
public getDefaultCfg() {
return {
rankdir: "LR",
nodesep: 0, // 节点水平间距(px)
ranksep: 40, // 每一层节点之间间距
begin: [0, 0], // 布局的起点位置
};
}
/**
* 执行布局
*/
public execute() {
const self = this;
const { nodes, edges, ranksep, nodesep, begin } = self;
if (!nodes) return;
const layerMap: Map<number, Node[]> = new Map();
nodes.forEach((item: any, index, arr) => {
if (!layerMap.has(item.level)) {
layerMap.set(
item.level,
arr.filter((node: any) => node.level === item.level)
);
}
});
// TODO 重新调整层级
const startX = begin[0];
const startY = begin[1];
const size = layerMap.size;
const maxWidth = size * nodeWidth + (size - 1) * ranksep;
const keyHr: any = {};
layerMap.forEach((list, key) => {
const sum = list.reduce((pre: any, curr: any) => {
return pre + curr.size[1];
}, 0);
let v = sum + (list.length - 1) * nodesep;
keyHr[key] = v;
});
const offsetX = startX + maxWidth;
// y轴始终以正中间为中心。
const centerLine = startY;
const comboSpace = 200;
let arr = Array.from(layerMap.keys()).sort((a, b) => {
return a-b;
});
let min: any = null;
if (arr[0] < 1) {
min = Math.abs(arr[0]);
}
arr.forEach((key, i) => {
let keyLevel = arr.at(-(i+1)) ?? -1;
if (min !== null) {
keyLevel = keyLevel + min;
}
let value = layerMap.get(key) || [];
let d = keyLevel === maxLevel ? size - 1 : keyLevel;
const x = offsetX - d * ((size > 3 ? nodeWidth/1.5 : nodeWidth) + ranksep);
const sortNodes = value.sort((x: any, y: any) => y.order - x.order);
/** 此处需要判断是否在同一个combo中。 */
const comboMap: Map<string, Node[]> = new Map();
sortNodes.forEach((e: any) => {
let comboId = e.comboId;
let v = comboMap.get(comboId);
if (!v) {
comboMap.set(comboId, [e]);
} else {
v.push(e);
comboMap.set(comboId, v);
}
})
const y = centerLine + keyHr[key] / 2 + Array.from(comboMap.keys()).length / 2 * comboSpace;
let preY = y;
comboMap.forEach((value, key) => {
value.forEach((e: any, index) => {
const { size } = e;
const margin = index === 0 ? 0 : nodesep;
preY = preY - size[1] - margin;
if ((value.length - 1) * size[1] == preY) { //解决整个页面刚好都是节点的异常
preY = preY - 80;
} else {
preY = (value.length == 1 && preY === 0) ? 60 : preY;//解决==0时combo显示不正确问题,http://test.csylcloud.com:8380/browse/WZL-970
}
e.x = x;
e.y = preY;
});
preY = preY - comboSpace;
})
});
if (self.onLayoutEnd) self.onLayoutEnd();
}
public getType() {
return 'lineageLayout';
}
}
G6.registerLayout('lineageLayout', CustomDagreLayout);