@antv/layout 0.3.22 → 0.3.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/layout.min.js +1 -1
- package/dist/layout.min.js.map +1 -1
- package/es/layout/comboCombined.d.ts +3 -3
- package/es/layout/comboCombined.js +39 -26
- package/es/layout/comboCombined.js.map +1 -1
- package/lib/layout/comboCombined.d.ts +3 -3
- package/lib/layout/comboCombined.js +38 -23
- package/lib/layout/comboCombined.js.map +1 -1
- package/package.json +1 -1
- package/src/layout/comboCombined.ts +86 -38
|
@@ -3,18 +3,32 @@
|
|
|
3
3
|
* @author shiwu.wyy@antfin.com
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import {
|
|
7
7
|
Edge,
|
|
8
8
|
Combo,
|
|
9
9
|
OutNode,
|
|
10
10
|
PointTuple,
|
|
11
11
|
ComboTree,
|
|
12
|
-
ComboCombinedLayoutOptions
|
|
13
|
-
} from
|
|
12
|
+
ComboCombinedLayoutOptions,
|
|
13
|
+
} from './types';
|
|
14
14
|
import { FORCE_LAYOUT_TYPE_MAP } from './constants';
|
|
15
|
-
import { Base } from
|
|
16
|
-
import {
|
|
17
|
-
|
|
15
|
+
import { Base } from './base';
|
|
16
|
+
import {
|
|
17
|
+
isArray,
|
|
18
|
+
isNumber,
|
|
19
|
+
isFunction,
|
|
20
|
+
traverseTreeUp,
|
|
21
|
+
isObject,
|
|
22
|
+
getLayoutBBox,
|
|
23
|
+
} from '../util';
|
|
24
|
+
import {
|
|
25
|
+
CircularLayout,
|
|
26
|
+
ConcentricLayout,
|
|
27
|
+
GridLayout,
|
|
28
|
+
RadialLayout,
|
|
29
|
+
GForceLayout,
|
|
30
|
+
MDSLayout,
|
|
31
|
+
} from '.';
|
|
18
32
|
|
|
19
33
|
type Node = OutNode & {
|
|
20
34
|
depth?: number;
|
|
@@ -29,7 +43,6 @@ type Node = OutNode & {
|
|
|
29
43
|
* combined two layouts (inner and outer) for graph with combos
|
|
30
44
|
*/
|
|
31
45
|
export class ComboCombinedLayout extends Base {
|
|
32
|
-
|
|
33
46
|
/** 布局中心 */
|
|
34
47
|
public center: PointTuple = [0, 0];
|
|
35
48
|
|
|
@@ -52,7 +65,11 @@ export class ComboCombinedLayout extends Base {
|
|
|
52
65
|
public outerLayout: any;
|
|
53
66
|
|
|
54
67
|
/** combo 内部的布局算法,默认为 concentric */
|
|
55
|
-
public innerLayout:
|
|
68
|
+
public innerLayout:
|
|
69
|
+
| ConcentricLayout
|
|
70
|
+
| CircularLayout
|
|
71
|
+
| GridLayout
|
|
72
|
+
| RadialLayout;
|
|
56
73
|
|
|
57
74
|
/** Combo 内部的 padding */
|
|
58
75
|
public comboPadding:
|
|
@@ -101,7 +118,7 @@ export class ComboCombinedLayout extends Base {
|
|
|
101
118
|
public run() {
|
|
102
119
|
const self = this;
|
|
103
120
|
const { nodes, edges, combos, comboEdges, center } = self;
|
|
104
|
-
|
|
121
|
+
|
|
105
122
|
const nodeMap: any = {};
|
|
106
123
|
nodes.forEach((node) => {
|
|
107
124
|
nodeMap[node.id] = node;
|
|
@@ -128,10 +145,15 @@ export class ComboCombinedLayout extends Base {
|
|
|
128
145
|
fx: innerNode.fx || comboMap[cTree.id].fx,
|
|
129
146
|
fy: innerNode.fy || comboMap[cTree.id].fy,
|
|
130
147
|
mass: innerNode.mass || comboMap[cTree.id].mass,
|
|
131
|
-
size: innerNode.size
|
|
148
|
+
size: innerNode.size,
|
|
132
149
|
};
|
|
133
150
|
outerNodes.push(oNode);
|
|
134
|
-
if (
|
|
151
|
+
if (
|
|
152
|
+
!isNaN(oNode.x) &&
|
|
153
|
+
oNode.x !== 0 &&
|
|
154
|
+
!isNaN(oNode.y) &&
|
|
155
|
+
oNode.y !== 0
|
|
156
|
+
) {
|
|
135
157
|
allHaveNoPosition = false;
|
|
136
158
|
} else {
|
|
137
159
|
oNode.x = Math.random() * 100;
|
|
@@ -148,7 +170,12 @@ export class ComboCombinedLayout extends Base {
|
|
|
148
170
|
// 代表节点的节点
|
|
149
171
|
const oNode: Node = { ...node };
|
|
150
172
|
outerNodes.push(oNode);
|
|
151
|
-
if (
|
|
173
|
+
if (
|
|
174
|
+
!isNaN(oNode.x) &&
|
|
175
|
+
oNode.x !== 0 &&
|
|
176
|
+
!isNaN(oNode.y) &&
|
|
177
|
+
oNode.y !== 0
|
|
178
|
+
) {
|
|
152
179
|
allHaveNoPosition = false;
|
|
153
180
|
} else {
|
|
154
181
|
oNode.x = Math.random() * 100;
|
|
@@ -161,12 +188,14 @@ export class ComboCombinedLayout extends Base {
|
|
|
161
188
|
const sourceAncestorId = nodeAncestorIdMap[edge.source] || edge.source;
|
|
162
189
|
const targetAncestorId = nodeAncestorIdMap[edge.target] || edge.target;
|
|
163
190
|
// 若两个点的祖先都在力导图的节点中,且是不同的节点,创建一条链接两个祖先的边到力导图的边中
|
|
164
|
-
if (
|
|
191
|
+
if (
|
|
192
|
+
sourceAncestorId !== targetAncestorId &&
|
|
165
193
|
outerNodeIds.includes(sourceAncestorId) &&
|
|
166
|
-
outerNodeIds.includes(targetAncestorId)
|
|
194
|
+
outerNodeIds.includes(targetAncestorId)
|
|
195
|
+
) {
|
|
167
196
|
outerEdges.push({
|
|
168
197
|
source: sourceAncestorId,
|
|
169
|
-
target: targetAncestorId
|
|
198
|
+
target: targetAncestorId,
|
|
170
199
|
});
|
|
171
200
|
}
|
|
172
201
|
});
|
|
@@ -179,19 +208,22 @@ export class ComboCombinedLayout extends Base {
|
|
|
179
208
|
} else {
|
|
180
209
|
const outerData = {
|
|
181
210
|
nodes: outerNodes,
|
|
182
|
-
edges: outerEdges
|
|
211
|
+
edges: outerEdges,
|
|
183
212
|
};
|
|
184
213
|
|
|
185
214
|
// 需要使用一个同步的布局
|
|
186
215
|
// @ts-ignore
|
|
187
|
-
const outerLayout =
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
216
|
+
const outerLayout =
|
|
217
|
+
this.outerLayout ||
|
|
218
|
+
new GForceLayout({
|
|
219
|
+
gravity: 1,
|
|
220
|
+
factor: 4,
|
|
221
|
+
linkDistance: (edge: any, source: any, target: any) => {
|
|
222
|
+
const nodeSize =
|
|
223
|
+
((source.size?.[0] || 30) + (target.size?.[0] || 30)) / 2;
|
|
224
|
+
return Math.min(nodeSize * 1.5, 700);
|
|
225
|
+
},
|
|
226
|
+
});
|
|
195
227
|
const outerLayoutType = outerLayout.getType?.();
|
|
196
228
|
outerLayout.updateCfg({
|
|
197
229
|
center,
|
|
@@ -201,7 +233,8 @@ export class ComboCombinedLayout extends Base {
|
|
|
201
233
|
});
|
|
202
234
|
// 若所有 outerNodes 都没有位置,且 outerLayout 是力导家族的布局,则先执行 preset mds 或 grid
|
|
203
235
|
if (allHaveNoPosition && FORCE_LAYOUT_TYPE_MAP[outerLayoutType]) {
|
|
204
|
-
const outerLayoutPreset =
|
|
236
|
+
const outerLayoutPreset =
|
|
237
|
+
outerNodes.length < 100 ? new MDSLayout() : new GridLayout();
|
|
205
238
|
outerLayoutPreset.layout(outerData);
|
|
206
239
|
}
|
|
207
240
|
outerLayout.layout(outerData);
|
|
@@ -235,8 +268,8 @@ export class ComboCombinedLayout extends Base {
|
|
|
235
268
|
if (!innerGraph) continue;
|
|
236
269
|
innerGraph.nodes.forEach((node: OutNode) => {
|
|
237
270
|
if (!innerGraph.visited) {
|
|
238
|
-
node.x +=
|
|
239
|
-
node.y +=
|
|
271
|
+
node.x += innerGraph.x || 0;
|
|
272
|
+
node.y += innerGraph.y || 0;
|
|
240
273
|
}
|
|
241
274
|
if (nodeMap[node.id]) {
|
|
242
275
|
nodeMap[node.id].x = node.x;
|
|
@@ -257,7 +290,9 @@ export class ComboCombinedLayout extends Base {
|
|
|
257
290
|
const innerGraphs: any = {};
|
|
258
291
|
|
|
259
292
|
// @ts-ignore
|
|
260
|
-
const innerGraphLayout: any =
|
|
293
|
+
const innerGraphLayout: any =
|
|
294
|
+
this.innerLayout ||
|
|
295
|
+
new ConcentricLayout({ type: 'concentric', sortBy: 'id' });
|
|
261
296
|
innerGraphLayout.center = [0, 0];
|
|
262
297
|
innerGraphLayout.preventOverlap = true;
|
|
263
298
|
innerGraphLayout.nodeSpacing = spacing;
|
|
@@ -270,11 +305,13 @@ export class ComboCombinedLayout extends Base {
|
|
|
270
305
|
if (!treeNode.children?.length) {
|
|
271
306
|
// 空 combo
|
|
272
307
|
if (treeNode.itemType === 'combo') {
|
|
273
|
-
const treeNodeSize = padding
|
|
308
|
+
const treeNodeSize = padding
|
|
309
|
+
? [padding * 2, padding * 2]
|
|
310
|
+
: [30, 30];
|
|
274
311
|
innerGraphs[treeNode.id] = {
|
|
275
312
|
id: treeNode.id,
|
|
276
313
|
nodes: [],
|
|
277
|
-
size: treeNodeSize
|
|
314
|
+
size: treeNodeSize,
|
|
278
315
|
};
|
|
279
316
|
}
|
|
280
317
|
} else {
|
|
@@ -287,19 +324,25 @@ export class ComboCombinedLayout extends Base {
|
|
|
287
324
|
const innerGraphNodeIds = innerGraphNodes.map((node) => node.id);
|
|
288
325
|
const innerGraphData = {
|
|
289
326
|
nodes: innerGraphNodes,
|
|
290
|
-
edges: edges.filter(
|
|
327
|
+
edges: edges.filter(
|
|
328
|
+
(edge) =>
|
|
329
|
+
innerGraphNodeIds.includes(edge.source) &&
|
|
330
|
+
innerGraphNodeIds.includes(edge.target)
|
|
331
|
+
),
|
|
291
332
|
};
|
|
292
333
|
let minNodeSize = Infinity;
|
|
293
334
|
innerGraphNodes.forEach((node) => {
|
|
294
335
|
// @ts-ignore
|
|
295
|
-
if (!node.size)
|
|
336
|
+
if (!node.size)
|
|
337
|
+
node.size = innerGraphs[node.id]?.size ||
|
|
338
|
+
(nodeSize as Function)?.(node) || [30, 30];
|
|
296
339
|
if (isNumber(node.size)) node.size = [node.size, node.size];
|
|
297
340
|
if (minNodeSize > node.size[0]) minNodeSize = node.size[0];
|
|
298
341
|
if (minNodeSize > node.size[1]) minNodeSize = node.size[1];
|
|
299
342
|
});
|
|
300
343
|
|
|
301
344
|
// 根据节点数量、spacing,调整布局参数
|
|
302
|
-
|
|
345
|
+
|
|
303
346
|
innerGraphLayout.layout(innerGraphData);
|
|
304
347
|
const { minX, minY, maxX, maxY } = getLayoutBBox(innerGraphNodes);
|
|
305
348
|
// move the innerGraph to [0, 0],for later controled by parent layout
|
|
@@ -308,11 +351,14 @@ export class ComboCombinedLayout extends Base {
|
|
|
308
351
|
node.x -= center.x;
|
|
309
352
|
node.y -= center.y;
|
|
310
353
|
});
|
|
311
|
-
const
|
|
354
|
+
const innerGraphWidth =
|
|
355
|
+
Math.max(maxX - minX, minNodeSize) + padding * 2;
|
|
356
|
+
const innerGraphHeight =
|
|
357
|
+
Math.max(maxY - minY, minNodeSize) + padding * 2;
|
|
312
358
|
innerGraphs[treeNode.id] = {
|
|
313
359
|
id: treeNode.id,
|
|
314
360
|
nodes: innerGraphNodes,
|
|
315
|
-
size: [
|
|
361
|
+
size: [innerGraphWidth, innerGraphHeight],
|
|
316
362
|
};
|
|
317
363
|
}
|
|
318
364
|
return true;
|
|
@@ -347,8 +393,10 @@ export class ComboCombinedLayout extends Base {
|
|
|
347
393
|
if (isArray(d.size)) {
|
|
348
394
|
const res = d.size[0] > d.size[1] ? d.size[0] : d.size[1];
|
|
349
395
|
return (res + spacing) / 2;
|
|
350
|
-
}
|
|
351
|
-
|
|
396
|
+
}
|
|
397
|
+
if (isObject(d.size)) {
|
|
398
|
+
const res =
|
|
399
|
+
d.size.width > d.size.height ? d.size.width : d.size.height;
|
|
352
400
|
return (res + spacing) / 2;
|
|
353
401
|
}
|
|
354
402
|
return (d.size + spacing) / 2;
|
|
@@ -392,6 +440,6 @@ export class ComboCombinedLayout extends Base {
|
|
|
392
440
|
this.comboPadding = comboPaddingFunc;
|
|
393
441
|
}
|
|
394
442
|
public getType() {
|
|
395
|
-
return
|
|
443
|
+
return 'comboCombined';
|
|
396
444
|
}
|
|
397
445
|
}
|