@antv/layout 2.0.0-alpha.2 → 2.0.0-alpha.3
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/index.js +1202 -1239
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +2 -2
- package/dist/index.min.js.map +1 -1
- package/dist/worker.js +1 -1
- package/dist/worker.js.map +1 -1
- package/lib/algorithm/antv-dagre/index.js +10 -8
- package/lib/algorithm/antv-dagre/index.js.map +1 -1
- package/lib/algorithm/antv-dagre/types.d.ts +25 -3
- package/lib/algorithm/base-layout.d.ts +1 -0
- package/lib/algorithm/base-layout.js +5 -3
- package/lib/algorithm/base-layout.js.map +1 -1
- package/lib/algorithm/d3-force/index.d.ts +2 -2
- package/lib/algorithm/d3-force/index.js +59 -97
- package/lib/algorithm/d3-force/index.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/util/object.d.ts +1 -2
- package/lib/util/object.js +1 -4
- package/lib/util/object.js.map +1 -1
- package/lib/worker.js +763 -799
- package/lib/worker.js.map +1 -1
- package/package.json +1 -1
- package/src/algorithm/antv-dagre/index.ts +11 -12
- package/src/algorithm/antv-dagre/types.ts +25 -3
- package/src/algorithm/base-layout.ts +13 -8
- package/src/algorithm/d3-force/index.ts +67 -117
- package/src/util/object.ts +0 -4
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { isNumber } from '@antv/util';
|
|
2
|
-
import { BaseLayout } from '../base-layout';
|
|
3
2
|
import type { NodeData, PointObject } from '../../types';
|
|
4
3
|
import { parsePoint } from '../../util';
|
|
5
4
|
import { formatNumberFn, formatSizeFn } from '../../util/format';
|
|
6
5
|
import { parseSize } from '../../util/size';
|
|
6
|
+
import { BaseLayout } from '../base-layout';
|
|
7
7
|
import { DagreGraph, GraphNode } from './graph';
|
|
8
8
|
import { layout } from './layout';
|
|
9
9
|
import { AntVDagreLayoutOptions } from './types';
|
|
@@ -50,18 +50,15 @@ export class AntVDagreLayout extends BaseLayout<AntVDagreLayoutOptions> {
|
|
|
50
50
|
sortByCombo,
|
|
51
51
|
// focusNode,
|
|
52
52
|
preset,
|
|
53
|
+
ranksepFunc,
|
|
54
|
+
nodesepFunc,
|
|
53
55
|
} = options;
|
|
54
56
|
|
|
55
|
-
const ranksepfunc = formatNumberFn(
|
|
56
|
-
|
|
57
|
-
DEFAULTS_LAYOUT_OPTIONS.ranksep as number,
|
|
58
|
-
);
|
|
59
|
-
const nodesepfunc = formatNumberFn(
|
|
60
|
-
nodesep,
|
|
61
|
-
DEFAULTS_LAYOUT_OPTIONS.nodesep as number,
|
|
62
|
-
);
|
|
57
|
+
const ranksepfunc = formatNumberFn(ranksepFunc, ranksep ?? 50);
|
|
58
|
+
const nodesepfunc = formatNumberFn(nodesepFunc, nodesep ?? 50);
|
|
63
59
|
let horisep: (d?: NodeData | undefined) => number = nodesepfunc;
|
|
64
60
|
let vertisep: (d?: NodeData | undefined) => number = ranksepfunc;
|
|
61
|
+
|
|
65
62
|
if (rankdir === 'LR' || rankdir === 'RL') {
|
|
66
63
|
horisep = ranksepfunc;
|
|
67
64
|
vertisep = nodesepfunc;
|
|
@@ -80,9 +77,10 @@ export class AntVDagreLayout extends BaseLayout<AntVDagreLayoutOptions> {
|
|
|
80
77
|
const edges = this.model.edges();
|
|
81
78
|
|
|
82
79
|
nodes.forEach((node) => {
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
const
|
|
80
|
+
const raw = node._original;
|
|
81
|
+
const size = parseSize(nodeSizeFunc(raw));
|
|
82
|
+
const verti = vertisep(raw);
|
|
83
|
+
const hori = horisep(raw);
|
|
86
84
|
const width = size[0] + 2 * hori;
|
|
87
85
|
const height = size[1] + 2 * verti;
|
|
88
86
|
const layer = node.data?.layer;
|
|
@@ -150,6 +148,7 @@ export class AntVDagreLayout extends BaseLayout<AntVDagreLayoutOptions> {
|
|
|
150
148
|
acyclicer: 'greedy',
|
|
151
149
|
ranker,
|
|
152
150
|
rankdir,
|
|
151
|
+
nodesep,
|
|
153
152
|
align,
|
|
154
153
|
});
|
|
155
154
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BaseLayoutOptions } from '../base-layout';
|
|
2
1
|
import { ID, NodeData, Point, Size } from '../../types';
|
|
2
|
+
import { BaseLayoutOptions } from '../base-layout';
|
|
3
3
|
|
|
4
4
|
export type DagreRankdir =
|
|
5
5
|
| 'TB'
|
|
@@ -83,7 +83,7 @@ export interface AntVDagreLayoutOptions extends BaseLayoutOptions {
|
|
|
83
83
|
* <en/> The horizontal gap between nodes (px) in the case of rankdir is 'TB' or 'BT'. The vertical gap between nodes (px) in the case of rankdir is 'LR' or 'RL'. nodesepFunc has a higher priority
|
|
84
84
|
* @defaultValue 50
|
|
85
85
|
*/
|
|
86
|
-
nodesep?: number
|
|
86
|
+
nodesep?: number;
|
|
87
87
|
/**
|
|
88
88
|
* <zh/> 层间距(px)
|
|
89
89
|
*
|
|
@@ -94,7 +94,29 @@ export interface AntVDagreLayoutOptions extends BaseLayoutOptions {
|
|
|
94
94
|
* <en/> The vertical gap between levels (px) in the case of rankdir is 'TB' or 'BT'. The horizontal gap between levels (px) in the case of rankdir is 'LR' or 'RL'. ranksepFunc has a higher priority
|
|
95
95
|
* @defaultValue 50
|
|
96
96
|
*/
|
|
97
|
-
ranksep?: number
|
|
97
|
+
ranksep?: number;
|
|
98
|
+
/**
|
|
99
|
+
* <zh/> 节点间距(px)的回调函数,通过该参数可以对不同节点设置不同的节点间距
|
|
100
|
+
*
|
|
101
|
+
* <en/> The callback function of the node spacing (px), which can be used to set different node spacing for different nodes
|
|
102
|
+
* @remarks
|
|
103
|
+
* <zh/> 在 rankdir 为 'TB' 或 'BT' 时是节点的水平间距;在 rankdir 为 'LR' 或 'RL' 时代表节点的竖直方向间距。优先级高于 nodesep,即若设置了 nodesepFunc,则 nodesep 不生效
|
|
104
|
+
*
|
|
105
|
+
* <en/> The horizontal spacing of the node in the case of rankdir is 'TB' or 'BT', and the vertical spacing of the node in the case of rankdir is 'LR' or 'RL'. The priority is higher than nodesep, that is, if nodesepFunc is set, nodesep does not take effect
|
|
106
|
+
* @param d - <zh/> 节点实例 | <en/> Node instance
|
|
107
|
+
*/
|
|
108
|
+
nodesepFunc?: (d?: NodeData) => number;
|
|
109
|
+
/**
|
|
110
|
+
* <zh/> 层间距(px)的回调函数
|
|
111
|
+
*
|
|
112
|
+
* <en/> The callback function of the layer spacing (px)
|
|
113
|
+
* @remarks
|
|
114
|
+
* <zh/> 在 rankdir 为 'TB' 或 'BT' 时是竖直方向相邻层间距;在 rankdir 为 'LR' 或 'RL' 时代表水平方向相邻层间距。优先级高于 nodesep,即若设置了 nodesepFunc,则 nodesep 不生效
|
|
115
|
+
*
|
|
116
|
+
* <en/> The vertical spacing of adjacent layers in the case of rankdir is 'TB' or 'BT', and the horizontal spacing of adjacent layers in the case of rankdir is 'LR' or 'RL'. The priority is higher than nodesep, that is, if nodesepFunc is set, nodesep does not take effect
|
|
117
|
+
* @param d - <zh/> 节点实例 | <en/> Node instance
|
|
118
|
+
*/
|
|
119
|
+
ranksepFunc?: (d?: NodeData) => number;
|
|
98
120
|
/**
|
|
99
121
|
* <zh/> 是否同时计算边上的的控制点位置
|
|
100
122
|
*
|
|
@@ -2,12 +2,7 @@ import type { GraphLib } from '../model/data';
|
|
|
2
2
|
import { RuntimeContext } from '../runtime/context';
|
|
3
3
|
import { Supervisor } from '../runtime/supervisor';
|
|
4
4
|
import type { GraphData, GraphEdge, GraphNode, Point } from '../types';
|
|
5
|
-
import {
|
|
6
|
-
import type {
|
|
7
|
-
BaseLayoutOptions,
|
|
8
|
-
Layout,
|
|
9
|
-
LayoutWithIterations,
|
|
10
|
-
} from './types';
|
|
5
|
+
import type { BaseLayoutOptions, Layout, LayoutWithIterations } from './types';
|
|
11
6
|
|
|
12
7
|
export type { BaseLayoutOptions };
|
|
13
8
|
|
|
@@ -35,18 +30,28 @@ export abstract class BaseLayout<
|
|
|
35
30
|
protected supervisor: Supervisor | null = null;
|
|
36
31
|
|
|
37
32
|
constructor(options?: Partial<O>) {
|
|
38
|
-
this.initialOptions = mergeOptions<O>(
|
|
33
|
+
this.initialOptions = this.mergeOptions<O>(
|
|
34
|
+
this.getDefaultOptions(),
|
|
35
|
+
options,
|
|
36
|
+
);
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
get options(): O {
|
|
42
40
|
return this.runtimeOptions || this.initialOptions;
|
|
43
41
|
}
|
|
44
42
|
|
|
43
|
+
protected mergeOptions<O>(base: O, patch?: Partial<O>): O {
|
|
44
|
+
return Object.assign({}, base, patch || {});
|
|
45
|
+
}
|
|
46
|
+
|
|
45
47
|
public async execute(
|
|
46
48
|
data: GraphData,
|
|
47
49
|
userOptions?: Partial<O>,
|
|
48
50
|
): Promise<void> {
|
|
49
|
-
this.runtimeOptions = mergeOptions<O>(
|
|
51
|
+
this.runtimeOptions = this.mergeOptions<O>(
|
|
52
|
+
this.initialOptions,
|
|
53
|
+
userOptions,
|
|
54
|
+
);
|
|
50
55
|
const { node, edge, enableWorker } = this.runtimeOptions;
|
|
51
56
|
|
|
52
57
|
this.context = new RuntimeContext(data, { node, edge });
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
forceX,
|
|
11
11
|
forceY,
|
|
12
12
|
} from 'd3-force';
|
|
13
|
-
import { BaseLayoutWithIterations } from '../base-layout';
|
|
14
13
|
import type { ID, Position } from '../../types';
|
|
15
14
|
import { assignDefined, normalizeViewport } from '../../util';
|
|
16
15
|
import { formatNodeSizeFn } from '../../util/format';
|
|
16
|
+
import { BaseLayoutWithIterations } from '../base-layout';
|
|
17
17
|
import forceInABox from './force-in-a-box';
|
|
18
18
|
import type {
|
|
19
19
|
D3ForceCommonOptions,
|
|
@@ -25,29 +25,20 @@ import type {
|
|
|
25
25
|
export type { D3ForceLayoutOptions };
|
|
26
26
|
|
|
27
27
|
const DEFAULTS_LAYOUT_OPTIONS: Partial<D3ForceLayoutOptions> = {
|
|
28
|
-
|
|
28
|
+
link: {
|
|
29
|
+
id: (d) => String(d.id),
|
|
30
|
+
},
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
edgeIterations: 1,
|
|
32
|
+
manyBody: {
|
|
33
|
+
strength: -30,
|
|
34
|
+
},
|
|
34
35
|
|
|
35
36
|
preventOverlap: false,
|
|
36
37
|
nodeSize: 10,
|
|
37
38
|
nodeSpacing: 0,
|
|
38
|
-
collideStrength: 1,
|
|
39
|
-
collideIterations: 1,
|
|
40
|
-
|
|
41
|
-
nodeStrength: -30,
|
|
42
|
-
distanceMin: undefined,
|
|
43
|
-
distanceMax: undefined,
|
|
44
|
-
theta: undefined,
|
|
45
39
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
alphaDecay: 1 - Math.pow(0.001, 1 / 300),
|
|
49
|
-
alphaTarget: 0,
|
|
50
|
-
velocityDecay: 0.4,
|
|
40
|
+
x: false,
|
|
41
|
+
y: false,
|
|
51
42
|
|
|
52
43
|
clustering: false,
|
|
53
44
|
clusterNodeStrength: -1,
|
|
@@ -84,7 +75,7 @@ export class D3ForceLayout<
|
|
|
84
75
|
return DEFAULTS_LAYOUT_OPTIONS as T;
|
|
85
76
|
}
|
|
86
77
|
|
|
87
|
-
protected mergeOptions(base: T, patch?: Partial<T>): T {
|
|
78
|
+
protected mergeOptions<T>(base: T, patch?: Partial<T>): T {
|
|
88
79
|
return deepMix({}, base, patch) as T;
|
|
89
80
|
}
|
|
90
81
|
|
|
@@ -301,22 +292,17 @@ export class D3ForceLayout<
|
|
|
301
292
|
}
|
|
302
293
|
|
|
303
294
|
private getCenterOptions(options: T): T['center'] | undefined {
|
|
304
|
-
if (
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
options.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
y: viewport.height / 2,
|
|
316
|
-
strength: options.centerStrength,
|
|
317
|
-
}) as T['center'];
|
|
318
|
-
}
|
|
319
|
-
return undefined;
|
|
295
|
+
if (options.center === false) return undefined;
|
|
296
|
+
|
|
297
|
+
const viewport = normalizeViewport({
|
|
298
|
+
width: options.width,
|
|
299
|
+
height: options.height,
|
|
300
|
+
});
|
|
301
|
+
return assignDefined({}, options.center || {}, {
|
|
302
|
+
x: viewport.width / 2,
|
|
303
|
+
y: viewport.height / 2,
|
|
304
|
+
strength: options.centerStrength,
|
|
305
|
+
}) as T['center'];
|
|
320
306
|
}
|
|
321
307
|
|
|
322
308
|
protected setupCenterForce(simulation: Simulation<N, E>, options: T) {
|
|
@@ -342,21 +328,14 @@ export class D3ForceLayout<
|
|
|
342
328
|
}
|
|
343
329
|
|
|
344
330
|
private getManyBodyOptions(options: T): D3ForceLayoutOptions['manyBody'] {
|
|
345
|
-
if (
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
options.
|
|
349
|
-
options.
|
|
350
|
-
options.
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
strength: options.nodeStrength,
|
|
354
|
-
distanceMin: options.distanceMin,
|
|
355
|
-
distanceMax: options.distanceMax,
|
|
356
|
-
theta: options.theta,
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
return undefined;
|
|
331
|
+
if (options.manyBody === false) return undefined;
|
|
332
|
+
|
|
333
|
+
return assignDefined({}, options.manyBody || {}, {
|
|
334
|
+
strength: options.nodeStrength,
|
|
335
|
+
distanceMin: options.distanceMin,
|
|
336
|
+
distanceMax: options.distanceMax,
|
|
337
|
+
theta: options.theta,
|
|
338
|
+
});
|
|
360
339
|
}
|
|
361
340
|
|
|
362
341
|
protected setupManyBodyForce(simulation: Simulation<N, E>, options: T) {
|
|
@@ -386,21 +365,14 @@ export class D3ForceLayout<
|
|
|
386
365
|
}
|
|
387
366
|
|
|
388
367
|
private getLinkOptions(options: T): D3ForceLayoutOptions['link'] {
|
|
389
|
-
if (
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
options.
|
|
393
|
-
options.
|
|
394
|
-
options.
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
id: options.edgeId,
|
|
398
|
-
distance: options.linkDistance,
|
|
399
|
-
strength: options.edgeStrength,
|
|
400
|
-
iterations: options.edgeIterations,
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
return undefined;
|
|
368
|
+
if (options.link === false) return undefined;
|
|
369
|
+
|
|
370
|
+
return assignDefined({}, options.link || {}, {
|
|
371
|
+
id: options.edgeId,
|
|
372
|
+
distance: options.linkDistance,
|
|
373
|
+
strength: options.edgeStrength,
|
|
374
|
+
iterations: options.edgeIterations,
|
|
375
|
+
});
|
|
404
376
|
}
|
|
405
377
|
|
|
406
378
|
protected setupLinkForce(simulation: Simulation<N, E>, options: T) {
|
|
@@ -429,30 +401,23 @@ export class D3ForceLayout<
|
|
|
429
401
|
}
|
|
430
402
|
|
|
431
403
|
private getCollisionOptions(options: T): D3ForceLayoutOptions['collide'] {
|
|
432
|
-
if (
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
options.
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
return assignDefined({}, options.collide || {}, {
|
|
450
|
-
radius,
|
|
451
|
-
strength: options.collideStrength,
|
|
452
|
-
iterations: options.collideIterations,
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
return undefined;
|
|
404
|
+
if (options.preventOverlap === false || options.collide === false)
|
|
405
|
+
return undefined;
|
|
406
|
+
|
|
407
|
+
const radius =
|
|
408
|
+
options.nodeSize || options.nodeSpacing
|
|
409
|
+
? (d: NodeDatum) =>
|
|
410
|
+
formatNodeSizeFn(
|
|
411
|
+
options.nodeSize,
|
|
412
|
+
options.nodeSpacing,
|
|
413
|
+
)(d._original) / 2
|
|
414
|
+
: undefined;
|
|
415
|
+
|
|
416
|
+
return assignDefined({}, options.collide || {}, {
|
|
417
|
+
radius: options.collide || radius,
|
|
418
|
+
strength: options.collideStrength,
|
|
419
|
+
iterations: options.collideIterations,
|
|
420
|
+
});
|
|
456
421
|
}
|
|
457
422
|
|
|
458
423
|
protected setupCollisionForce(simulation: Simulation<N, E>, options: T) {
|
|
@@ -479,20 +444,13 @@ export class D3ForceLayout<
|
|
|
479
444
|
}
|
|
480
445
|
|
|
481
446
|
private getXForceOptions(options: T): D3ForceLayoutOptions['x'] {
|
|
482
|
-
if (
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
options.
|
|
487
|
-
options.
|
|
488
|
-
)
|
|
489
|
-
const center = this.getCenterOptions(options);
|
|
490
|
-
return assignDefined({}, options.x || {}, {
|
|
491
|
-
x: options.forceXPosition ?? (center && center.x),
|
|
492
|
-
strength: options.forceXStrength,
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
return undefined;
|
|
447
|
+
if (options.x === false) return undefined;
|
|
448
|
+
|
|
449
|
+
const center = this.getCenterOptions(options);
|
|
450
|
+
return assignDefined({}, options.x || {}, {
|
|
451
|
+
x: options.forceXPosition ?? (center && center.x),
|
|
452
|
+
strength: options.forceXStrength,
|
|
453
|
+
});
|
|
496
454
|
}
|
|
497
455
|
|
|
498
456
|
protected setupXForce(simulation: Simulation<N, E>, options: T) {
|
|
@@ -516,21 +474,13 @@ export class D3ForceLayout<
|
|
|
516
474
|
}
|
|
517
475
|
|
|
518
476
|
private getYForceOptions(options: T): D3ForceLayoutOptions['y'] {
|
|
519
|
-
if (
|
|
520
|
-
options.y !== undefined ||
|
|
521
|
-
options.forceYPosition !== undefined ||
|
|
522
|
-
options.forceYStrength !== undefined ||
|
|
523
|
-
options.width !== undefined ||
|
|
524
|
-
options.height !== undefined
|
|
525
|
-
) {
|
|
526
|
-
const center = this.getCenterOptions(options);
|
|
527
|
-
return assignDefined({}, options.y || {}, {
|
|
528
|
-
y: options.forceYPosition ?? (center && center.y),
|
|
529
|
-
strength: options.forceYStrength,
|
|
530
|
-
});
|
|
531
|
-
}
|
|
477
|
+
if (options.y === false) return undefined;
|
|
532
478
|
|
|
533
|
-
|
|
479
|
+
const center = this.getCenterOptions(options);
|
|
480
|
+
return assignDefined({}, options.y || {}, {
|
|
481
|
+
y: options.forceYPosition ?? (center && center.y),
|
|
482
|
+
strength: options.forceYStrength,
|
|
483
|
+
});
|
|
534
484
|
}
|
|
535
485
|
|
|
536
486
|
protected setupYForce(simulation: Simulation<N, E>, options: T) {
|