@krainovsd/graph 0.12.0-beta.6 → 0.13.0-beta3
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/lib/cjs/index.cjs +566 -371
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/esm/index.js +5 -4
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/module/GraphCanvas/GraphCanvas.js +41 -46
- package/lib/esm/module/GraphCanvas/GraphCanvas.js.map +1 -1
- package/lib/esm/module/GraphCanvas/constants/index.js +12 -0
- package/lib/esm/module/GraphCanvas/constants/index.js.map +1 -0
- package/lib/esm/module/GraphCanvas/constants/link-settings.js +1 -0
- package/lib/esm/module/GraphCanvas/constants/link-settings.js.map +1 -1
- package/lib/esm/module/GraphCanvas/lib/utils/calculate-curve-link-position-by-node.js +42 -0
- package/lib/esm/module/GraphCanvas/lib/utils/calculate-curve-link-position-by-node.js.map +1 -0
- package/lib/esm/module/GraphCanvas/lib/utils/calculate-link-position-by-node.js +37 -35
- package/lib/esm/module/GraphCanvas/lib/utils/calculate-link-position-by-node.js.map +1 -1
- package/lib/esm/module/GraphCanvas/lib/utils/link-by-pointer-getter.js +72 -22
- package/lib/esm/module/GraphCanvas/lib/utils/link-by-pointer-getter.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/draw-links.js +70 -17
- package/lib/esm/module/GraphCanvas/slices/draw-links.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/init-pointer.js +6 -0
- package/lib/esm/module/GraphCanvas/slices/init-pointer.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/init-resize.js +7 -0
- package/lib/esm/module/GraphCanvas/slices/init-resize.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/init-zoom.js +5 -2
- package/lib/esm/module/GraphCanvas/slices/init-zoom.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/update-link-cache.js +30 -0
- package/lib/esm/module/GraphCanvas/slices/update-link-cache.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/update-node-cache.js +103 -97
- package/lib/esm/module/GraphCanvas/slices/update-node-cache.js.map +1 -1
- package/lib/index.d.ts +71 -47
- package/package.json +3 -2
package/lib/cjs/index.cjs
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
|
|
5
|
+
const jsHelpers = require('@krainovsd/js-helpers');
|
|
5
6
|
const d3Force = require('d3-force');
|
|
6
7
|
const d3Zoom = require('d3-zoom');
|
|
7
|
-
const jsHelpers = require('@krainovsd/js-helpers');
|
|
8
8
|
const d3Array = require('d3-array');
|
|
9
9
|
const d3Selection = require('d3-selection');
|
|
10
10
|
const d3Drag = require('d3-drag');
|
|
@@ -41,158 +41,6 @@ const FORCE_SETTINGS = {
|
|
|
41
41
|
collideRadius: null,
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
-
const GRAPH_SETTINGS = {
|
|
45
|
-
zoomExtent: [0.3, 10],
|
|
46
|
-
translateExtent: [[], []],
|
|
47
|
-
translateExtentEnable: true,
|
|
48
|
-
translateExtentCoefficient: [3, 3],
|
|
49
|
-
dragPlaceCoefficient: dragPlaceCoefficientGetter,
|
|
50
|
-
zoomInitial: null,
|
|
51
|
-
showDrawTime: true,
|
|
52
|
-
showDrawTimeEveryTick: false,
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const HIGHLIGHT_SETTINGS = {
|
|
56
|
-
highlightByHoverNode: true,
|
|
57
|
-
highlightByHoverLink: true,
|
|
58
|
-
highlightUpFrames: 5,
|
|
59
|
-
highlightDownFrames: 5,
|
|
60
|
-
linkHoverExtraZone: 2,
|
|
61
|
-
/** Node */
|
|
62
|
-
highlightByNodeOnlyRoot: true,
|
|
63
|
-
highlightByNodeForNodeColorFading: false,
|
|
64
|
-
highlightByNodeForNodeColor: null,
|
|
65
|
-
highlightByNodeForNodeSizingAdditional: 0.5,
|
|
66
|
-
highlightByNodeForNodeSizingAdditionalCoefficient: 0.35,
|
|
67
|
-
highlightByNodeForNodeFadingMin: 0.21,
|
|
68
|
-
highlightByNodeForNodeBorderColor: null,
|
|
69
|
-
highlightByNodeForNodeBorderSizingAdditional: 0,
|
|
70
|
-
highlightByLinkForNodeColorFading: false,
|
|
71
|
-
highlightByLinkForNodeColor: null,
|
|
72
|
-
highlightByLinkForNodeSizingAdditional: 0.5,
|
|
73
|
-
highlightByLinkForNodeSizingAdditionalCoefficient: 0.35,
|
|
74
|
-
highlightByLinkForNodeFadingMin: 0.21,
|
|
75
|
-
highlightByLinkForNodeBorderColor: null,
|
|
76
|
-
highlightByLinkForNodeBorderSizingAdditional: 0,
|
|
77
|
-
/** Text */
|
|
78
|
-
highlightByNodeForTextShiftXAdditional: 0,
|
|
79
|
-
highlightByNodeForTextShiftYAdditional: 2,
|
|
80
|
-
highlightByNodeForTextSizingAdditional: 1,
|
|
81
|
-
highlightByNodeForTextWeightAdditional: 0,
|
|
82
|
-
highlightByNodeForTextFadingMin: 0.21,
|
|
83
|
-
highlightByLinkForTextShiftXAdditional: 0,
|
|
84
|
-
highlightByLinkForTextShiftYAdditional: 2,
|
|
85
|
-
highlightByLinkForTextSizingAdditional: 1,
|
|
86
|
-
highlightByLinkForTextWeightAdditional: 0,
|
|
87
|
-
highlightByLinkForTextFadingMin: 0.21,
|
|
88
|
-
/** Label */
|
|
89
|
-
highlightByNodeForLabelFadingMin: 0.21,
|
|
90
|
-
highlightByNodeForLabelSizingAdditional: 1,
|
|
91
|
-
highlightByNodeForLabelWeightAdditional: 0,
|
|
92
|
-
highlightByLinkForLabelFadingMin: 0.21,
|
|
93
|
-
highlightByLinkForLabelSizingAdditional: 1,
|
|
94
|
-
highlightByLinkForLabelWeightAdditional: 0,
|
|
95
|
-
/** Link */
|
|
96
|
-
highlightByNodeForLinkFadingMin: 0.21,
|
|
97
|
-
highlightByNodeForLinkSizeAdditional: 0,
|
|
98
|
-
highlightByNodeForLinkColor: null,
|
|
99
|
-
highlightByLinkForLinkFadingMin: 0.21,
|
|
100
|
-
highlightByLinkForLinkSizeAdditional: 0,
|
|
101
|
-
highlightByLinkForLinkColor: null,
|
|
102
|
-
/** Arrow */
|
|
103
|
-
highlightByNodeForArrowFadingMin: 0.21,
|
|
104
|
-
highlightByNodeForArrowSizeAdditional: 0,
|
|
105
|
-
highlightByNodeForArrowColor: null,
|
|
106
|
-
highlightByNodeForArrowBorderColor: null,
|
|
107
|
-
highlightByNodeForArrowBorderSizingAdditional: 0,
|
|
108
|
-
highlightByLinkForArrowFadingMin: 0.21,
|
|
109
|
-
highlightByLinkForArrowSizeAdditional: 0,
|
|
110
|
-
highlightByLinkForArrowColor: null,
|
|
111
|
-
highlightByLinkForArrowBorderColor: null,
|
|
112
|
-
highlightByLinkForArrowBorderSizingAdditional: 0,
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const LINK_SETTINGS = {
|
|
116
|
-
prettyDraw: true,
|
|
117
|
-
linkScaleSwitch: 1,
|
|
118
|
-
linkColorAfterScaleSwitch: "#000000FF",
|
|
119
|
-
linkColorBeforeScaleSwitch: "#999",
|
|
120
|
-
linkWidthAfterScaleSwitch: 0.1,
|
|
121
|
-
linkWidthBeforeScaleSwitch: 1,
|
|
122
|
-
arrow: true,
|
|
123
|
-
arrowByHighlight: true,
|
|
124
|
-
particles: true,
|
|
125
|
-
particleFlexSpeed: true,
|
|
126
|
-
particleFlexSpeedCoefficient: 4,
|
|
127
|
-
};
|
|
128
|
-
const LINK_OPTIONS = {
|
|
129
|
-
alpha: 1,
|
|
130
|
-
arrowAlpha: 1,
|
|
131
|
-
arrowSize: 2,
|
|
132
|
-
arrowBorderColor: "#000000FF",
|
|
133
|
-
arrowBorderWidth: 0.1,
|
|
134
|
-
particleAlpha: 1,
|
|
135
|
-
particleColor: "#000000FF",
|
|
136
|
-
particleBorderColor: "#000000FF",
|
|
137
|
-
particleBorderWidth: 0.1,
|
|
138
|
-
particleCount: 2,
|
|
139
|
-
particleRadius: 0.5,
|
|
140
|
-
particleSteps: 60,
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const NODE_SETTINGS = {
|
|
144
|
-
nodeRadiusFlexible: true,
|
|
145
|
-
nodeRadiusLinkCountForStep: 5,
|
|
146
|
-
nodeRadiusIncrementByStep: 1,
|
|
147
|
-
nodeRadiusMaxLinearSteps: 5,
|
|
148
|
-
nodeRadiusLinkCountDividerForLog: 25,
|
|
149
|
-
nodeRadiusLogFactor: 2.5,
|
|
150
|
-
nodeSizeFlexible: true,
|
|
151
|
-
nodeSizeLinkCountForStep: 5,
|
|
152
|
-
nodeSizeIncrementByStep: 0.1,
|
|
153
|
-
nodeSizeMaxLinearSteps: 5,
|
|
154
|
-
nodeSizeLinkCountDividerForLog: 25,
|
|
155
|
-
nodeSizeLogFactor: 2.5,
|
|
156
|
-
textScaleMin: 1.5,
|
|
157
|
-
textScaleMax: 18,
|
|
158
|
-
textSizeMin: 3.5,
|
|
159
|
-
textSizeMax: 1.5,
|
|
160
|
-
textShiftYMin: 4,
|
|
161
|
-
textShiftYMax: 2.5,
|
|
162
|
-
textNodeDebug: false,
|
|
163
|
-
};
|
|
164
|
-
const NODE_OPTIONS = {
|
|
165
|
-
shape: "circle",
|
|
166
|
-
height: 10,
|
|
167
|
-
width: 15,
|
|
168
|
-
borderRadius: 0,
|
|
169
|
-
radius: 4,
|
|
170
|
-
alpha: 1,
|
|
171
|
-
labelXPadding: 1,
|
|
172
|
-
labelYPadding: 1,
|
|
173
|
-
borderWidth: 0.1,
|
|
174
|
-
borderColor: "#000000FF",
|
|
175
|
-
textAlpha: 1,
|
|
176
|
-
textWidth: 20,
|
|
177
|
-
textShiftX: 0,
|
|
178
|
-
textFont: "Arial",
|
|
179
|
-
textAlign: "center",
|
|
180
|
-
textColor: "#333",
|
|
181
|
-
textStyle: "normal",
|
|
182
|
-
textWeight: 500,
|
|
183
|
-
textGap: 0,
|
|
184
|
-
label: null,
|
|
185
|
-
labelAlpha: 1,
|
|
186
|
-
labelAlign: "center",
|
|
187
|
-
labelColor: "#333",
|
|
188
|
-
labelFont: "Arial",
|
|
189
|
-
labelGap: 0,
|
|
190
|
-
labelSize: 3.5,
|
|
191
|
-
labelStyle: "normal",
|
|
192
|
-
labelWeight: 500,
|
|
193
|
-
labelWidth: 20,
|
|
194
|
-
};
|
|
195
|
-
|
|
196
44
|
function forceSettingsGetter(settings, prevSettings) {
|
|
197
45
|
return {
|
|
198
46
|
...(prevSettings ?? FORCE_SETTINGS),
|
|
@@ -573,50 +421,52 @@ function nodeIterationExtractor(node, i, nodes, state, option, optionConstantGet
|
|
|
573
421
|
return customOptions;
|
|
574
422
|
}
|
|
575
423
|
|
|
576
|
-
function calculateLinkPositionByNode(
|
|
577
|
-
const source = link.source;
|
|
578
|
-
const target = link.target;
|
|
579
|
-
if (typeof source != "object" || typeof target != "object")
|
|
580
|
-
return null;
|
|
424
|
+
function calculateLinkPositionByNode(xStart, yStart, xEnd, yEnd, sourceNode, targetNode, arrowSize = 0) {
|
|
581
425
|
const sourcePoint = getLinkPoint({
|
|
426
|
+
xStart,
|
|
427
|
+
yStart,
|
|
428
|
+
xEnd,
|
|
429
|
+
yEnd,
|
|
582
430
|
arrowSize: 0,
|
|
583
|
-
node:
|
|
584
|
-
oppositeNode: target,
|
|
585
|
-
});
|
|
431
|
+
node: sourceNode});
|
|
586
432
|
const targetPoint = getLinkPoint({
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
433
|
+
xStart: xEnd,
|
|
434
|
+
yStart: yEnd,
|
|
435
|
+
xEnd: xStart,
|
|
436
|
+
yEnd: yStart,
|
|
437
|
+
arrowSize: arrowSize > 0 ? arrowSize * 0.9 : 0,
|
|
438
|
+
node: targetNode});
|
|
439
|
+
const targetPointArrow = getLinkPoint({
|
|
440
|
+
xStart: xEnd,
|
|
441
|
+
yStart: yEnd,
|
|
442
|
+
xEnd: xStart,
|
|
443
|
+
yEnd: yStart,
|
|
444
|
+
arrowSize: 0,
|
|
445
|
+
node: targetNode});
|
|
593
446
|
const distance = targetPoint && sourcePoint
|
|
594
447
|
? Math.sqrt((targetPoint.x - sourcePoint.x) ** 2 + (targetPoint.y - sourcePoint.y) ** 2)
|
|
595
448
|
: 0;
|
|
596
449
|
return {
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
450
|
+
xStart: sourcePoint.x,
|
|
451
|
+
yStart: sourcePoint.y,
|
|
452
|
+
xEnd: targetPoint.x,
|
|
453
|
+
yEnd: targetPoint.y,
|
|
454
|
+
xEndArrow: targetPointArrow.x,
|
|
455
|
+
yEndArrow: targetPointArrow.y,
|
|
601
456
|
distance,
|
|
602
457
|
};
|
|
603
458
|
}
|
|
604
459
|
function getLinkPoint(opts) {
|
|
605
|
-
if (opts.node.x == undefined ||
|
|
606
|
-
opts.node.y == undefined ||
|
|
607
|
-
opts.oppositeNode.x == undefined ||
|
|
608
|
-
opts.oppositeNode.y == undefined)
|
|
609
|
-
return null;
|
|
610
460
|
let nodePoint;
|
|
611
461
|
switch (opts.node._shape) {
|
|
612
462
|
case "circle": {
|
|
613
463
|
nodePoint = getCircleIntersection({
|
|
614
|
-
x: opts.
|
|
615
|
-
y: opts.
|
|
464
|
+
x: opts.xStart,
|
|
465
|
+
y: opts.yStart,
|
|
616
466
|
radius: (opts.node._radius ?? COMMON_SETTINGS.nodeRadius) +
|
|
617
467
|
(opts.node._borderWidth ? opts.node._borderWidth / 2 : 0),
|
|
618
|
-
oppositeX: opts.
|
|
619
|
-
oppositeY: opts.
|
|
468
|
+
oppositeX: opts.xEnd,
|
|
469
|
+
oppositeY: opts.yEnd,
|
|
620
470
|
arrowSize: opts.arrowSize,
|
|
621
471
|
});
|
|
622
472
|
break;
|
|
@@ -625,23 +475,23 @@ function getLinkPoint(opts) {
|
|
|
625
475
|
case "text": {
|
|
626
476
|
nodePoint = getRectangleIntersection({
|
|
627
477
|
arrowSize: opts.arrowSize,
|
|
628
|
-
x: opts.
|
|
629
|
-
y: opts.
|
|
478
|
+
x: opts.xStart,
|
|
479
|
+
y: opts.yStart,
|
|
630
480
|
height: (opts.node._height ?? COMMON_SETTINGS.nodeSize) + (opts.node._borderWidth ?? 0),
|
|
631
481
|
width: (opts.node._width ?? COMMON_SETTINGS.nodeSize) + (opts.node._borderWidth ?? 0),
|
|
632
|
-
oppositeX: opts.
|
|
633
|
-
oppositeY: opts.
|
|
482
|
+
oppositeX: opts.xEnd,
|
|
483
|
+
oppositeY: opts.yEnd,
|
|
634
484
|
borderRadius: opts.node._shape === "text" ? 0 : (opts.node._borderRadius ?? 0),
|
|
635
485
|
});
|
|
636
486
|
break;
|
|
637
487
|
}
|
|
638
488
|
default: {
|
|
639
489
|
nodePoint = getCircleIntersection({
|
|
640
|
-
x: opts.
|
|
641
|
-
y: opts.
|
|
490
|
+
x: opts.xStart,
|
|
491
|
+
y: opts.yStart,
|
|
642
492
|
radius: opts.node._radius ?? COMMON_SETTINGS.nodeRadius,
|
|
643
|
-
oppositeX: opts.
|
|
644
|
-
oppositeY: opts.
|
|
493
|
+
oppositeX: opts.xEnd,
|
|
494
|
+
oppositeY: opts.yEnd,
|
|
645
495
|
arrowSize: opts.arrowSize,
|
|
646
496
|
});
|
|
647
497
|
}
|
|
@@ -922,31 +772,34 @@ function getParticlePosition(opts) {
|
|
|
922
772
|
}
|
|
923
773
|
}
|
|
924
774
|
|
|
925
|
-
function linkByPointerGetter({ areaRect, areaTransform, mouseEvent, links, linkHoverExtraZone, }) {
|
|
775
|
+
function linkByPointerGetter({ areaRect, areaTransform, mouseEvent, links, linkHoverExtraZone, curve, }) {
|
|
926
776
|
if (!areaRect)
|
|
927
777
|
return undefined;
|
|
928
778
|
const [pointerX, pointerY] = pointerGetter(mouseEvent, areaRect, areaTransform);
|
|
929
779
|
return d3Array.greatest(links, (link) => {
|
|
930
|
-
if (
|
|
931
|
-
|
|
780
|
+
if (!jsHelpers.isObject(link.source) ||
|
|
781
|
+
!jsHelpers.isObject(link.target) ||
|
|
782
|
+
link.source.visible === false ||
|
|
783
|
+
link.target.visible === false)
|
|
784
|
+
return;
|
|
785
|
+
const x1 = (link._x1 ?? link.source.x);
|
|
786
|
+
const y1 = (link._y1 ?? link.source.y);
|
|
787
|
+
const x2 = (link._x2 ?? link.target.x);
|
|
788
|
+
const y2 = (link._y2 ?? link.target.y);
|
|
789
|
+
const cx = link._cx ?? 0;
|
|
790
|
+
const cy = link._cy ?? 0;
|
|
791
|
+
return curve
|
|
792
|
+
? hitTestQuadratic(pointerX, pointerY, x1, y1, cx, cy, x2, y2, linkHoverExtraZone)
|
|
793
|
+
? link.index
|
|
794
|
+
: undefined
|
|
795
|
+
: isNearLink(pointerX, pointerY, x1, y1, x2, y2, linkHoverExtraZone)
|
|
796
|
+
? link.index
|
|
797
|
+
: undefined;
|
|
932
798
|
});
|
|
933
799
|
}
|
|
934
|
-
function isNearLink(
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
link.source.visible === false ||
|
|
938
|
-
link.target.visible === false)
|
|
939
|
-
return false;
|
|
940
|
-
const x1 = link.source.x;
|
|
941
|
-
const y1 = link.source.y;
|
|
942
|
-
const x2 = link.target.x;
|
|
943
|
-
const y2 = link.target.y;
|
|
944
|
-
const distance = distanceToLine(mouseX, mouseY, x1, y1, x2, y2);
|
|
945
|
-
return distance <= threshold;
|
|
946
|
-
}
|
|
947
|
-
function distanceToLine(x, y, x1, y1, x2, y2) {
|
|
948
|
-
const A = x - x1;
|
|
949
|
-
const B = y - y1;
|
|
800
|
+
function isNearLink(px, py, x1, y1, x2, y2, threshold = 2) {
|
|
801
|
+
const A = px - x1;
|
|
802
|
+
const B = py - y1;
|
|
950
803
|
const C = x2 - x1;
|
|
951
804
|
const D = y2 - y1;
|
|
952
805
|
const dot = A * C + B * D;
|
|
@@ -968,9 +821,56 @@ function distanceToLine(x, y, x1, y1, x2, y2) {
|
|
|
968
821
|
xx = x1 + param * C;
|
|
969
822
|
yy = y1 + param * D;
|
|
970
823
|
}
|
|
971
|
-
const dx =
|
|
972
|
-
const dy =
|
|
973
|
-
return Math.sqrt(dx * dx + dy * dy);
|
|
824
|
+
const dx = px - xx;
|
|
825
|
+
const dy = py - yy;
|
|
826
|
+
return Math.sqrt(dx * dx + dy * dy) <= threshold;
|
|
827
|
+
}
|
|
828
|
+
function hitTestQuadratic(px, py, x0, y0, xc, yc, x2, y2, tol) {
|
|
829
|
+
const bb = bezierBBox(x0, y0, xc, yc, x2, y2);
|
|
830
|
+
if (px < bb.minX - tol || px > bb.maxX + tol || py < bb.minY - tol || py > bb.maxY + tol) {
|
|
831
|
+
return false;
|
|
832
|
+
}
|
|
833
|
+
const chord = Math.hypot(x2 - x0, y2 - y0);
|
|
834
|
+
const contLen = Math.hypot(xc - x0, yc - y0) + Math.hypot(x2 - xc, y2 - yc);
|
|
835
|
+
const approxLen = (chord + contLen) / 2;
|
|
836
|
+
const steps = Math.max(16, Math.ceil(approxLen / 1));
|
|
837
|
+
const tol2 = tol * tol;
|
|
838
|
+
for (let i = 0; i <= steps; i++) {
|
|
839
|
+
const t = i / steps;
|
|
840
|
+
const mt = 1 - t;
|
|
841
|
+
const x = mt * mt * x0 + 2 * mt * t * xc + t * t * x2;
|
|
842
|
+
const y = mt * mt * y0 + 2 * mt * t * yc + t * t * y2;
|
|
843
|
+
const dx = px - x;
|
|
844
|
+
const dy = py - y;
|
|
845
|
+
if (dx * dx + dy * dy <= tol2)
|
|
846
|
+
return true;
|
|
847
|
+
}
|
|
848
|
+
return false;
|
|
849
|
+
}
|
|
850
|
+
function bezierBBox(x0, y0, x1, y1, x2, y2) {
|
|
851
|
+
function extrema(p0, p1, p2) {
|
|
852
|
+
const denom = p0 - 2 * p1 + p2;
|
|
853
|
+
if (denom === 0)
|
|
854
|
+
return [];
|
|
855
|
+
const t = (p0 - p1) / denom;
|
|
856
|
+
return t > 0 && t < 1 ? [t] : [];
|
|
857
|
+
}
|
|
858
|
+
const ts = [...extrema(x0, x1, x2), ...extrema(y0, y1, y2), 0, 1];
|
|
859
|
+
let maxX = -Infinity, maxY = -Infinity, minX = Infinity, minY = Infinity;
|
|
860
|
+
for (const t of ts) {
|
|
861
|
+
const mt = 1 - t;
|
|
862
|
+
const x = mt * mt * x0 + 2 * mt * t * x1 + t * t * x2;
|
|
863
|
+
const y = mt * mt * y0 + 2 * mt * t * y1 + t * t * y2;
|
|
864
|
+
if (x < minX)
|
|
865
|
+
minX = x;
|
|
866
|
+
if (x > maxX)
|
|
867
|
+
maxX = x;
|
|
868
|
+
if (y < minY)
|
|
869
|
+
minY = y;
|
|
870
|
+
if (y > maxY)
|
|
871
|
+
maxY = y;
|
|
872
|
+
}
|
|
873
|
+
return { minX, minY, maxX, maxY };
|
|
974
874
|
}
|
|
975
875
|
|
|
976
876
|
function nodeHighlight(opts) {
|
|
@@ -1146,6 +1046,166 @@ function extractLinkPointIds(link) {
|
|
|
1146
1046
|
return { sourceId, targetId };
|
|
1147
1047
|
}
|
|
1148
1048
|
|
|
1049
|
+
const GRAPH_SETTINGS = {
|
|
1050
|
+
zoomExtent: [0.3, 10],
|
|
1051
|
+
translateExtent: [[], []],
|
|
1052
|
+
translateExtentEnable: true,
|
|
1053
|
+
translateExtentCoefficient: [3, 3],
|
|
1054
|
+
dragPlaceCoefficient: dragPlaceCoefficientGetter,
|
|
1055
|
+
zoomInitial: null,
|
|
1056
|
+
showDrawTime: true,
|
|
1057
|
+
showDrawTimeEveryTick: false,
|
|
1058
|
+
};
|
|
1059
|
+
|
|
1060
|
+
const HIGHLIGHT_SETTINGS = {
|
|
1061
|
+
highlightByHoverNode: true,
|
|
1062
|
+
highlightByHoverLink: true,
|
|
1063
|
+
highlightUpFrames: 5,
|
|
1064
|
+
highlightDownFrames: 5,
|
|
1065
|
+
linkHoverExtraZone: 2,
|
|
1066
|
+
/** Node */
|
|
1067
|
+
highlightByNodeOnlyRoot: true,
|
|
1068
|
+
highlightByNodeForNodeColorFading: false,
|
|
1069
|
+
highlightByNodeForNodeColor: null,
|
|
1070
|
+
highlightByNodeForNodeSizingAdditional: 0.5,
|
|
1071
|
+
highlightByNodeForNodeSizingAdditionalCoefficient: 0.35,
|
|
1072
|
+
highlightByNodeForNodeFadingMin: 0.21,
|
|
1073
|
+
highlightByNodeForNodeBorderColor: null,
|
|
1074
|
+
highlightByNodeForNodeBorderSizingAdditional: 0,
|
|
1075
|
+
highlightByLinkForNodeColorFading: false,
|
|
1076
|
+
highlightByLinkForNodeColor: null,
|
|
1077
|
+
highlightByLinkForNodeSizingAdditional: 0.5,
|
|
1078
|
+
highlightByLinkForNodeSizingAdditionalCoefficient: 0.35,
|
|
1079
|
+
highlightByLinkForNodeFadingMin: 0.21,
|
|
1080
|
+
highlightByLinkForNodeBorderColor: null,
|
|
1081
|
+
highlightByLinkForNodeBorderSizingAdditional: 0,
|
|
1082
|
+
/** Text */
|
|
1083
|
+
highlightByNodeForTextShiftXAdditional: 0,
|
|
1084
|
+
highlightByNodeForTextShiftYAdditional: 2,
|
|
1085
|
+
highlightByNodeForTextSizingAdditional: 1,
|
|
1086
|
+
highlightByNodeForTextWeightAdditional: 0,
|
|
1087
|
+
highlightByNodeForTextFadingMin: 0.21,
|
|
1088
|
+
highlightByLinkForTextShiftXAdditional: 0,
|
|
1089
|
+
highlightByLinkForTextShiftYAdditional: 2,
|
|
1090
|
+
highlightByLinkForTextSizingAdditional: 1,
|
|
1091
|
+
highlightByLinkForTextWeightAdditional: 0,
|
|
1092
|
+
highlightByLinkForTextFadingMin: 0.21,
|
|
1093
|
+
/** Label */
|
|
1094
|
+
highlightByNodeForLabelFadingMin: 0.21,
|
|
1095
|
+
highlightByNodeForLabelSizingAdditional: 1,
|
|
1096
|
+
highlightByNodeForLabelWeightAdditional: 0,
|
|
1097
|
+
highlightByLinkForLabelFadingMin: 0.21,
|
|
1098
|
+
highlightByLinkForLabelSizingAdditional: 1,
|
|
1099
|
+
highlightByLinkForLabelWeightAdditional: 0,
|
|
1100
|
+
/** Link */
|
|
1101
|
+
highlightByNodeForLinkFadingMin: 0.21,
|
|
1102
|
+
highlightByNodeForLinkSizeAdditional: 0,
|
|
1103
|
+
highlightByNodeForLinkColor: null,
|
|
1104
|
+
highlightByLinkForLinkFadingMin: 0.21,
|
|
1105
|
+
highlightByLinkForLinkSizeAdditional: 0,
|
|
1106
|
+
highlightByLinkForLinkColor: null,
|
|
1107
|
+
/** Arrow */
|
|
1108
|
+
highlightByNodeForArrowFadingMin: 0.21,
|
|
1109
|
+
highlightByNodeForArrowSizeAdditional: 0,
|
|
1110
|
+
highlightByNodeForArrowColor: null,
|
|
1111
|
+
highlightByNodeForArrowBorderColor: null,
|
|
1112
|
+
highlightByNodeForArrowBorderSizingAdditional: 0,
|
|
1113
|
+
highlightByLinkForArrowFadingMin: 0.21,
|
|
1114
|
+
highlightByLinkForArrowSizeAdditional: 0,
|
|
1115
|
+
highlightByLinkForArrowColor: null,
|
|
1116
|
+
highlightByLinkForArrowBorderColor: null,
|
|
1117
|
+
highlightByLinkForArrowBorderSizingAdditional: 0,
|
|
1118
|
+
};
|
|
1119
|
+
|
|
1120
|
+
const LINK_SETTINGS = {
|
|
1121
|
+
prettyDraw: true,
|
|
1122
|
+
curve: false,
|
|
1123
|
+
linkScaleSwitch: 1,
|
|
1124
|
+
linkColorAfterScaleSwitch: "#000000FF",
|
|
1125
|
+
linkColorBeforeScaleSwitch: "#999",
|
|
1126
|
+
linkWidthAfterScaleSwitch: 0.1,
|
|
1127
|
+
linkWidthBeforeScaleSwitch: 1,
|
|
1128
|
+
arrow: true,
|
|
1129
|
+
arrowByHighlight: true,
|
|
1130
|
+
particles: true,
|
|
1131
|
+
particleFlexSpeed: true,
|
|
1132
|
+
particleFlexSpeedCoefficient: 4,
|
|
1133
|
+
};
|
|
1134
|
+
const LINK_OPTIONS = {
|
|
1135
|
+
alpha: 1,
|
|
1136
|
+
arrowAlpha: 1,
|
|
1137
|
+
arrowSize: 2,
|
|
1138
|
+
arrowBorderColor: "#000000FF",
|
|
1139
|
+
arrowBorderWidth: 0.1,
|
|
1140
|
+
particleAlpha: 1,
|
|
1141
|
+
particleColor: "#000000FF",
|
|
1142
|
+
particleBorderColor: "#000000FF",
|
|
1143
|
+
particleBorderWidth: 0.1,
|
|
1144
|
+
particleCount: 2,
|
|
1145
|
+
particleRadius: 0.5,
|
|
1146
|
+
particleSteps: 60,
|
|
1147
|
+
};
|
|
1148
|
+
|
|
1149
|
+
const NODE_SETTINGS = {
|
|
1150
|
+
nodeRadiusFlexible: true,
|
|
1151
|
+
nodeRadiusLinkCountForStep: 5,
|
|
1152
|
+
nodeRadiusIncrementByStep: 1,
|
|
1153
|
+
nodeRadiusMaxLinearSteps: 5,
|
|
1154
|
+
nodeRadiusLinkCountDividerForLog: 25,
|
|
1155
|
+
nodeRadiusLogFactor: 2.5,
|
|
1156
|
+
nodeSizeFlexible: true,
|
|
1157
|
+
nodeSizeLinkCountForStep: 5,
|
|
1158
|
+
nodeSizeIncrementByStep: 0.1,
|
|
1159
|
+
nodeSizeMaxLinearSteps: 5,
|
|
1160
|
+
nodeSizeLinkCountDividerForLog: 25,
|
|
1161
|
+
nodeSizeLogFactor: 2.5,
|
|
1162
|
+
textScaleMin: 1.5,
|
|
1163
|
+
textScaleMax: 18,
|
|
1164
|
+
textSizeMin: 3.5,
|
|
1165
|
+
textSizeMax: 1.5,
|
|
1166
|
+
textShiftYMin: 4,
|
|
1167
|
+
textShiftYMax: 2.5,
|
|
1168
|
+
textNodeDebug: false,
|
|
1169
|
+
};
|
|
1170
|
+
const NODE_OPTIONS = {
|
|
1171
|
+
shape: "circle",
|
|
1172
|
+
height: 10,
|
|
1173
|
+
width: 15,
|
|
1174
|
+
borderRadius: 0,
|
|
1175
|
+
radius: 4,
|
|
1176
|
+
alpha: 1,
|
|
1177
|
+
labelXPadding: 1,
|
|
1178
|
+
labelYPadding: 1,
|
|
1179
|
+
borderWidth: 0.1,
|
|
1180
|
+
borderColor: "#000000FF",
|
|
1181
|
+
textAlpha: 1,
|
|
1182
|
+
textWidth: 20,
|
|
1183
|
+
textShiftX: 0,
|
|
1184
|
+
textFont: "Arial",
|
|
1185
|
+
textAlign: "center",
|
|
1186
|
+
textColor: "#333",
|
|
1187
|
+
textStyle: "normal",
|
|
1188
|
+
textWeight: 500,
|
|
1189
|
+
textGap: 0,
|
|
1190
|
+
label: null,
|
|
1191
|
+
labelAlpha: 1,
|
|
1192
|
+
labelAlign: "center",
|
|
1193
|
+
labelColor: "#333",
|
|
1194
|
+
labelFont: "Arial",
|
|
1195
|
+
labelGap: 0,
|
|
1196
|
+
labelSize: 3.5,
|
|
1197
|
+
labelStyle: "normal",
|
|
1198
|
+
labelWeight: 500,
|
|
1199
|
+
labelWidth: 20,
|
|
1200
|
+
};
|
|
1201
|
+
|
|
1202
|
+
const GRAPH_CACHE_TYPE = {
|
|
1203
|
+
NodeOptions: "nodeOptions",
|
|
1204
|
+
LinkOptions: "linkOptions",
|
|
1205
|
+
NodeText: "nodeText",
|
|
1206
|
+
NodeLabel: "nodeLabel",
|
|
1207
|
+
};
|
|
1208
|
+
|
|
1149
1209
|
function initArea() {
|
|
1150
1210
|
if (!this.area || !this.context || !this.container) {
|
|
1151
1211
|
this.container = d3Selection.create("div")
|
|
@@ -1227,6 +1287,42 @@ function initDnd() {
|
|
|
1227
1287
|
d3Selection.select(this.area).call(dragHandler);
|
|
1228
1288
|
}
|
|
1229
1289
|
|
|
1290
|
+
function calculateCurveLinkPositionByNode(xStart, yStart, xEnd, yEnd, sourceNode, targetNode, groupIndex, arrowSize = 0) {
|
|
1291
|
+
const sourceRadius = (sourceNode._radius ?? COMMON_SETTINGS.nodeRadius) + (sourceNode._borderWidth ?? 0) * 0.5;
|
|
1292
|
+
const targetRadius = (targetNode._radius ?? COMMON_SETTINGS.nodeRadius) + (targetNode._borderWidth ?? 0) * 0.5;
|
|
1293
|
+
const effectiveTargetRadius = targetRadius + arrowSize * 0.9;
|
|
1294
|
+
const mx = (xStart + xEnd) * 0.5;
|
|
1295
|
+
const my = (yStart + yEnd) * 0.5;
|
|
1296
|
+
const dx = xEnd - xStart;
|
|
1297
|
+
const dy = yEnd - yStart;
|
|
1298
|
+
const lenSq = dx * dx + dy * dy;
|
|
1299
|
+
const len = lenSq > 0 ? Math.sqrt(lenSq) : 1;
|
|
1300
|
+
const nx = -dy / len;
|
|
1301
|
+
const ny = dx / len;
|
|
1302
|
+
const offset = 0.12 * len * groupIndex;
|
|
1303
|
+
const xControl = mx + nx * offset;
|
|
1304
|
+
const yControl = my + ny * offset;
|
|
1305
|
+
const [xStartP, yStartP] = adjustPoint(xStart, yStart, xControl, yControl, sourceRadius);
|
|
1306
|
+
const [xEndP, yEndP] = adjustPoint(xEnd, yEnd, xControl, yControl, effectiveTargetRadius);
|
|
1307
|
+
const [xEndArrow, yEndArrow] = adjustPoint(xEnd, yEnd, xControl, yControl, targetRadius);
|
|
1308
|
+
return {
|
|
1309
|
+
xStart: xStartP,
|
|
1310
|
+
yStart: yStartP,
|
|
1311
|
+
xEnd: xEndP,
|
|
1312
|
+
yEnd: yEndP,
|
|
1313
|
+
xControl,
|
|
1314
|
+
yControl,
|
|
1315
|
+
xEndArrow,
|
|
1316
|
+
yEndArrow,
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
function adjustPoint(x, y, xControl, yControl, radius) {
|
|
1320
|
+
const dxToControl = xControl - x;
|
|
1321
|
+
const dyToControl = yControl - y;
|
|
1322
|
+
const distToControl = Math.sqrt(dxToControl * dxToControl + dyToControl * dyToControl) || 1;
|
|
1323
|
+
return [x + (dxToControl / distToControl) * radius, y + (dyToControl / distToControl) * radius];
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1230
1326
|
function getDrawLink() {
|
|
1231
1327
|
return function drawLink(link) {
|
|
1232
1328
|
if (!this.context ||
|
|
@@ -1342,23 +1438,62 @@ function getDrawLink() {
|
|
|
1342
1438
|
let yStart = link.source.y;
|
|
1343
1439
|
let xEnd = link.target.x;
|
|
1344
1440
|
let yEnd = link.target.y;
|
|
1441
|
+
let xControl = 0;
|
|
1442
|
+
let yControl = 0;
|
|
1443
|
+
let xEndArrow = xEnd;
|
|
1444
|
+
let yEndArrow = yEnd;
|
|
1345
1445
|
let linkDistance = 0;
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
(this.linkSettings.
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
xStart = position.
|
|
1353
|
-
xEnd = position.
|
|
1354
|
-
yStart = position.
|
|
1355
|
-
yEnd = position.
|
|
1446
|
+
const isHasArrow = this.linkSettings.arrow && arrowAlpha > 0;
|
|
1447
|
+
if (!this.linkSettings.curve) {
|
|
1448
|
+
if (this.linkSettings.prettyDraw ||
|
|
1449
|
+
this.linkSettings.particleFlexSpeed ||
|
|
1450
|
+
(this.linkSettings.arrow && arrowAlpha > 0)) {
|
|
1451
|
+
const position = calculateLinkPositionByNode(xStart, yStart, xEnd, yEnd, link.source, link.target, isHasArrow ? arrowSize : 0);
|
|
1452
|
+
xStart = position.xStart;
|
|
1453
|
+
xEnd = position.xEnd;
|
|
1454
|
+
yStart = position.yStart;
|
|
1455
|
+
yEnd = position.yEnd;
|
|
1456
|
+
xEndArrow = position.xEndArrow;
|
|
1457
|
+
yEndArrow = position.yEndArrow;
|
|
1356
1458
|
linkDistance = position.distance;
|
|
1357
1459
|
}
|
|
1460
|
+
link._x1 = xStart;
|
|
1461
|
+
link._y1 = yStart;
|
|
1462
|
+
link._x2 = xEnd;
|
|
1463
|
+
link._y2 = yEnd;
|
|
1464
|
+
link._ax = xEndArrow;
|
|
1465
|
+
link._ay = yEndArrow;
|
|
1466
|
+
this.context.moveTo(xStart, yStart);
|
|
1467
|
+
this.context.lineTo(xEnd, yEnd);
|
|
1468
|
+
this.context.stroke();
|
|
1469
|
+
}
|
|
1470
|
+
else {
|
|
1471
|
+
const position = calculateCurveLinkPositionByNode(xStart, yStart, xEnd, yEnd, link.source, link.target, link._groupIndex ?? 0, isHasArrow ? arrowSize : 0);
|
|
1472
|
+
xStart = position.xStart;
|
|
1473
|
+
yStart = position.yStart;
|
|
1474
|
+
xEnd = position.xEnd;
|
|
1475
|
+
yEnd = position.yEnd;
|
|
1476
|
+
xControl = position.xControl;
|
|
1477
|
+
yControl = position.yControl;
|
|
1478
|
+
xEndArrow = position.xEndArrow;
|
|
1479
|
+
yEndArrow = position.yEndArrow;
|
|
1480
|
+
link._x1 = position.xStart;
|
|
1481
|
+
link._y1 = position.yStart;
|
|
1482
|
+
link._x2 = position.xEnd;
|
|
1483
|
+
link._y2 = position.yEnd;
|
|
1484
|
+
link._cx = position.xControl;
|
|
1485
|
+
link._cy = position.yControl;
|
|
1486
|
+
link._ax = position.xEndArrow;
|
|
1487
|
+
link._ay = position.yEndArrow;
|
|
1488
|
+
this.context.beginPath();
|
|
1489
|
+
this.context.moveTo(position.xStart, position.yStart);
|
|
1490
|
+
this.context.quadraticCurveTo(position.xControl, position.yControl, position.xEnd, position.yEnd);
|
|
1491
|
+
this.context.setLineDash([]);
|
|
1492
|
+
// if (isDashed) {
|
|
1493
|
+
// this.context.setLineDash([10, 5]);
|
|
1494
|
+
// }
|
|
1495
|
+
this.context.stroke();
|
|
1358
1496
|
}
|
|
1359
|
-
this.context.moveTo(xStart, yStart);
|
|
1360
|
-
this.context.lineTo(xEnd, yEnd);
|
|
1361
|
-
this.context.stroke();
|
|
1362
1497
|
/** Particle */
|
|
1363
1498
|
if (this.linkSettings.particles &&
|
|
1364
1499
|
((this.highlightedNode &&
|
|
@@ -1426,15 +1561,28 @@ function getDrawLink() {
|
|
|
1426
1561
|
}
|
|
1427
1562
|
/** Arrow */
|
|
1428
1563
|
if (this.linkSettings.arrow && arrowAlpha > 0) {
|
|
1564
|
+
let angle = 0;
|
|
1565
|
+
if (!this.linkSettings.curve) {
|
|
1566
|
+
angle = Math.atan2(yEndArrow - yStart, xEndArrow - xStart);
|
|
1567
|
+
}
|
|
1568
|
+
else {
|
|
1569
|
+
const tangentX = 2 * (xEndArrow - xControl);
|
|
1570
|
+
const tangentY = 2 * (yEndArrow - yControl);
|
|
1571
|
+
if (Math.abs(tangentX) < 0.001 && Math.abs(tangentY) < 0.001) {
|
|
1572
|
+
angle = Math.atan2(yEndArrow - yControl, xEndArrow - xControl);
|
|
1573
|
+
}
|
|
1574
|
+
else {
|
|
1575
|
+
angle = Math.atan2(tangentY, tangentX);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1429
1578
|
this.context.beginPath();
|
|
1430
1579
|
this.context.globalAlpha = arrowAlpha;
|
|
1431
1580
|
this.context.strokeStyle = arrowBorderColor;
|
|
1432
1581
|
this.context.lineWidth = arrowBorderWidth;
|
|
1433
1582
|
this.context.fillStyle = arrowColor;
|
|
1434
|
-
|
|
1435
|
-
this.context.
|
|
1436
|
-
this.context.lineTo(
|
|
1437
|
-
this.context.lineTo(xEnd - arrowSize * Math.cos(angle + Math.PI / 6), yEnd - arrowSize * Math.sin(angle + Math.PI / 6));
|
|
1583
|
+
this.context.moveTo(xEndArrow, yEndArrow);
|
|
1584
|
+
this.context.lineTo(xEndArrow - arrowSize * Math.cos(angle - Math.PI / 6), yEndArrow - arrowSize * Math.sin(angle - Math.PI / 6));
|
|
1585
|
+
this.context.lineTo(xEndArrow - arrowSize * Math.cos(angle + Math.PI / 6), yEndArrow - arrowSize * Math.sin(angle + Math.PI / 6));
|
|
1438
1586
|
this.context.closePath();
|
|
1439
1587
|
this.context.fill();
|
|
1440
1588
|
if (arrowBorderWidth > 0) {
|
|
@@ -1958,6 +2106,7 @@ function initPointer() {
|
|
|
1958
2106
|
areaTransform: this.areaTransform,
|
|
1959
2107
|
mouseEvent: event,
|
|
1960
2108
|
links: this.links,
|
|
2109
|
+
curve: this.linkSettings.curve,
|
|
1961
2110
|
});
|
|
1962
2111
|
if (currentLink?.highlight != undefined)
|
|
1963
2112
|
highlightLink = currentLink?.highlight;
|
|
@@ -2019,6 +2168,7 @@ function initPointer() {
|
|
|
2019
2168
|
areaTransform: this.areaTransform,
|
|
2020
2169
|
mouseEvent: event,
|
|
2021
2170
|
links: this.links,
|
|
2171
|
+
curve: this.linkSettings.curve,
|
|
2022
2172
|
});
|
|
2023
2173
|
}
|
|
2024
2174
|
if (!currentNode)
|
|
@@ -2043,6 +2193,7 @@ function initPointer() {
|
|
|
2043
2193
|
areaTransform: this.areaTransform,
|
|
2044
2194
|
mouseEvent: event,
|
|
2045
2195
|
links: this.links,
|
|
2196
|
+
curve: this.linkSettings.curve,
|
|
2046
2197
|
});
|
|
2047
2198
|
return void this.listeners.onWheelClick.call(this, event, undefined, currentLink);
|
|
2048
2199
|
}
|
|
@@ -2064,6 +2215,7 @@ function initPointer() {
|
|
|
2064
2215
|
areaTransform: this.areaTransform,
|
|
2065
2216
|
mouseEvent: event,
|
|
2066
2217
|
links: this.links,
|
|
2218
|
+
curve: this.linkSettings.curve,
|
|
2067
2219
|
});
|
|
2068
2220
|
return void this.listeners.onContextMenu.call(this, event, undefined, currentLink);
|
|
2069
2221
|
}
|
|
@@ -2085,6 +2237,7 @@ function initPointer() {
|
|
|
2085
2237
|
areaTransform: this.areaTransform,
|
|
2086
2238
|
mouseEvent: event,
|
|
2087
2239
|
links: this.links,
|
|
2240
|
+
curve: this.linkSettings.curve,
|
|
2088
2241
|
});
|
|
2089
2242
|
return void this.listeners.onDoubleClick.call(this, event, undefined, currentLink);
|
|
2090
2243
|
}
|
|
@@ -2106,6 +2259,7 @@ function initPointer() {
|
|
|
2106
2259
|
areaTransform: this.areaTransform,
|
|
2107
2260
|
mouseEvent: event,
|
|
2108
2261
|
links: this.links,
|
|
2262
|
+
curve: this.linkSettings.curve,
|
|
2109
2263
|
});
|
|
2110
2264
|
return void this.listeners.onClick.call(this, event, undefined, currentLink);
|
|
2111
2265
|
}
|
|
@@ -2151,12 +2305,19 @@ function initResize() {
|
|
|
2151
2305
|
return;
|
|
2152
2306
|
}
|
|
2153
2307
|
this.updateSize();
|
|
2308
|
+
requestAnimationFrame(() => {
|
|
2309
|
+
this.updateSize();
|
|
2310
|
+
});
|
|
2154
2311
|
});
|
|
2155
2312
|
document.addEventListener("scroll", this.updateRect.bind(this), {
|
|
2156
2313
|
capture: true,
|
|
2157
2314
|
passive: true,
|
|
2158
2315
|
signal: abortController.signal,
|
|
2159
2316
|
});
|
|
2317
|
+
document.addEventListener("visibilitychange", () => {
|
|
2318
|
+
if (!document.hidden)
|
|
2319
|
+
this.updateRect();
|
|
2320
|
+
}, { signal: abortController.signal });
|
|
2160
2321
|
observer.observe(this.area);
|
|
2161
2322
|
}
|
|
2162
2323
|
|
|
@@ -2277,119 +2438,156 @@ function initCollideForce(forceUpdate) {
|
|
|
2277
2438
|
|
|
2278
2439
|
function updateLinkCache() {
|
|
2279
2440
|
this.linkOptionsCache = {};
|
|
2441
|
+
const groupMap = {};
|
|
2442
|
+
const groupSelfMap = {};
|
|
2280
2443
|
for (let i = 0; i < this.links.length; i++) {
|
|
2281
2444
|
const link = this.links[i];
|
|
2282
2445
|
const { sourceId, targetId } = extractLinkPointIds(link);
|
|
2283
2446
|
const linkOptions = linkIterationExtractor(link, i, this.links, this, this.linkSettings.options ?? {}, linkOptionsGetter);
|
|
2284
2447
|
const id = `${targetId}${sourceId}`;
|
|
2285
2448
|
this.linkOptionsCache[id] = linkOptions;
|
|
2449
|
+
if (this.linkSettings.curve) {
|
|
2450
|
+
if (sourceId === targetId) {
|
|
2451
|
+
groupSelfMap[id] ??= 0;
|
|
2452
|
+
link._groupIndex = ++groupSelfMap[id];
|
|
2453
|
+
link._self = true;
|
|
2454
|
+
continue;
|
|
2455
|
+
}
|
|
2456
|
+
const reverseId = `${sourceId}${targetId}`;
|
|
2457
|
+
groupMap[reverseId] ??= 0;
|
|
2458
|
+
groupMap[reverseId]++;
|
|
2459
|
+
groupMap[id] ??= 0;
|
|
2460
|
+
link._groupIndex = indexToPosition(++groupMap[id]);
|
|
2461
|
+
link._self = false;
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
if (this.linkSettings.curve) {
|
|
2465
|
+
for (const link of this.links) {
|
|
2466
|
+
const { sourceId, targetId } = extractLinkPointIds(link);
|
|
2467
|
+
const id = `${targetId}${sourceId}`;
|
|
2468
|
+
link._groupSize = link._self ? (groupSelfMap[id] ?? 1) : (groupMap[id] ?? 1);
|
|
2469
|
+
}
|
|
2286
2470
|
}
|
|
2287
2471
|
}
|
|
2472
|
+
function indexToPosition(n) {
|
|
2473
|
+
if (n === 1)
|
|
2474
|
+
return 0;
|
|
2475
|
+
const index = n >> 1;
|
|
2476
|
+
return n & 1 ? -(index * 2) : index * 2;
|
|
2477
|
+
// return n & 1 ? -(n >> 1) : n >> 1;
|
|
2478
|
+
}
|
|
2288
2479
|
|
|
2289
|
-
function updateNodeCache() {
|
|
2480
|
+
function updateNodeCache(types) {
|
|
2290
2481
|
this.nodeOptionsCache = {};
|
|
2291
2482
|
if (!this.context)
|
|
2292
2483
|
return;
|
|
2293
2484
|
for (let i = 0; i < this.nodes.length; i++) {
|
|
2294
2485
|
const node = this.nodes[i];
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2486
|
+
if (types === true || (jsHelpers.isObject(types) && types.options)) {
|
|
2487
|
+
const nodeOptions = nodeIterationExtractor(node, i, this.nodes, this, this.nodeSettings.options ?? {}, nodeOptionsGetter);
|
|
2488
|
+
const radius = nodeOptions.shape === "circle"
|
|
2489
|
+
? nodeRadiusGetter({
|
|
2490
|
+
radiusFlexible: this.nodeSettings.nodeRadiusFlexible,
|
|
2491
|
+
radiusInitial: nodeOptions.radius,
|
|
2492
|
+
radiusIncrementByStep: this.nodeSettings.nodeRadiusIncrementByStep,
|
|
2493
|
+
radiusLinkCountForStep: this.nodeSettings.nodeRadiusLinkCountForStep,
|
|
2494
|
+
radiusMaxLinearSteps: this.nodeSettings.nodeRadiusMaxLinearSteps,
|
|
2495
|
+
radiusLogFactor: this.nodeSettings.nodeRadiusLogFactor,
|
|
2496
|
+
radiusLinkCountDividerForLog: this.nodeSettings.nodeRadiusLinkCountDividerForLog,
|
|
2497
|
+
linkCount: node.linkCount,
|
|
2498
|
+
})
|
|
2499
|
+
: nodeOptions.radius;
|
|
2500
|
+
let width = nodeOptions.width;
|
|
2501
|
+
let height = nodeOptions.height;
|
|
2502
|
+
let labelSize = nodeOptions.labelSize;
|
|
2503
|
+
if (nodeOptions.shape === "square") {
|
|
2504
|
+
const size = nodeSizeGetter({
|
|
2505
|
+
heightInitial: nodeOptions.height,
|
|
2506
|
+
widthInitial: nodeOptions.width,
|
|
2507
|
+
linkCount: node.linkCount,
|
|
2508
|
+
sizeFlexible: this.nodeSettings.nodeSizeFlexible,
|
|
2509
|
+
sizeIncrementByStep: this.nodeSettings.nodeSizeIncrementByStep,
|
|
2510
|
+
sizeLinkCountForStep: this.nodeSettings.nodeSizeLinkCountForStep,
|
|
2511
|
+
sizeMaxLinearSteps: this.nodeSettings.nodeSizeMaxLinearSteps,
|
|
2512
|
+
sizeLogFactor: this.nodeSettings.nodeSizeLogFactor,
|
|
2513
|
+
sizeLinkCountDividerForLog: this.nodeSettings.nodeSizeLinkCountDividerForLog,
|
|
2514
|
+
});
|
|
2515
|
+
width = size.width;
|
|
2516
|
+
height = size.height;
|
|
2517
|
+
}
|
|
2518
|
+
if (nodeOptions.shape === "text") {
|
|
2519
|
+
width = nodeOptions.width;
|
|
2520
|
+
const size = nodeSizeGetter({
|
|
2521
|
+
heightInitial: nodeOptions.height,
|
|
2522
|
+
widthInitial: width,
|
|
2523
|
+
linkCount: node.linkCount,
|
|
2524
|
+
sizeFlexible: this.nodeSettings.nodeSizeFlexible,
|
|
2525
|
+
sizeIncrementByStep: this.nodeSettings.nodeSizeIncrementByStep,
|
|
2526
|
+
sizeLinkCountForStep: this.nodeSettings.nodeSizeLinkCountForStep,
|
|
2527
|
+
sizeMaxLinearSteps: this.nodeSettings.nodeSizeMaxLinearSteps,
|
|
2528
|
+
sizeLogFactor: this.nodeSettings.nodeSizeLogFactor,
|
|
2529
|
+
sizeLinkCountDividerForLog: this.nodeSettings.nodeSizeLinkCountDividerForLog,
|
|
2530
|
+
});
|
|
2531
|
+
labelSize *= size.additionalSizeCoefficient;
|
|
2532
|
+
}
|
|
2533
|
+
nodeOptions.width = node.visible === false ? 0 : width;
|
|
2534
|
+
nodeOptions.height = node.visible === false ? 0 : height;
|
|
2535
|
+
nodeOptions.radius = node.visible === false ? 0 : radius;
|
|
2536
|
+
nodeOptions.labelSize = labelSize;
|
|
2537
|
+
this.nodeOptionsCache[node.id] = nodeOptions;
|
|
2538
|
+
}
|
|
2539
|
+
const nodeOptions = this.nodeOptionsCache[node.id];
|
|
2540
|
+
/** label */
|
|
2541
|
+
if (types === true || (jsHelpers.isObject(types) && types.label)) {
|
|
2542
|
+
/** label in not text shape */
|
|
2543
|
+
if (nodeOptions.shape !== "text" && nodeOptions.label) {
|
|
2544
|
+
this.context.font = `${nodeOptions.labelStyle} normal ${nodeOptions.labelWeight} ${nodeOptions.labelSize}px ${nodeOptions.labelFont}`;
|
|
2545
|
+
this.context.fillStyle = nodeOptions.labelColor;
|
|
2546
|
+
this.context.textAlign = nodeOptions.labelAlign;
|
|
2547
|
+
if (nodeOptions.labelWidth == undefined ||
|
|
2548
|
+
this.context.measureText(nodeOptions.label).width <= nodeOptions.labelWidth) {
|
|
2549
|
+
this.cachedNodeLabel[node.id] = [nodeOptions.label];
|
|
2550
|
+
}
|
|
2551
|
+
const { lines } = getTextLines({
|
|
2552
|
+
context: this.context,
|
|
2553
|
+
maxWidth: nodeOptions.labelWidth,
|
|
2554
|
+
text: nodeOptions.label,
|
|
2555
|
+
textAlign: nodeOptions.labelAlign,
|
|
2556
|
+
textColor: nodeOptions.labelColor,
|
|
2557
|
+
textFont: nodeOptions.labelFont,
|
|
2558
|
+
textSize: nodeOptions.labelSize,
|
|
2559
|
+
textStyle: nodeOptions.labelStyle,
|
|
2560
|
+
textWeight: nodeOptions.labelWeight,
|
|
2561
|
+
});
|
|
2562
|
+
this.cachedNodeLabel[node.id] = lines;
|
|
2563
|
+
/** label in text shape */
|
|
2564
|
+
}
|
|
2565
|
+
else if (nodeOptions.shape === "text" && nodeOptions.label) {
|
|
2566
|
+
const textInfo = getTextLines({
|
|
2567
|
+
context: this.context,
|
|
2568
|
+
text: nodeOptions.label,
|
|
2569
|
+
textAlign: nodeOptions.labelAlign,
|
|
2570
|
+
textColor: nodeOptions.labelColor,
|
|
2571
|
+
textFont: nodeOptions.labelFont,
|
|
2572
|
+
textSize: nodeOptions.labelSize,
|
|
2573
|
+
maxWidth: nodeOptions.labelWidth,
|
|
2574
|
+
textStyle: nodeOptions.labelStyle,
|
|
2575
|
+
textWeight: nodeOptions.textWeight,
|
|
2576
|
+
});
|
|
2577
|
+
const textNodeParameters = [textInfo.currentMaxSize, nodeOptions.labelSize];
|
|
2578
|
+
const lines = textInfo.lines;
|
|
2579
|
+
const textSizeCoefficient = nodeOptions.labelSize / textNodeParameters[1];
|
|
2580
|
+
const maxSize = textNodeParameters[0] * textSizeCoefficient;
|
|
2581
|
+
nodeOptions.height =
|
|
2582
|
+
lines.length * nodeOptions.labelSize +
|
|
2583
|
+
(lines.length - 1) * nodeOptions.labelGap +
|
|
2584
|
+
nodeOptions.labelYPadding;
|
|
2585
|
+
nodeOptions.width = maxSize + nodeOptions.labelXPadding;
|
|
2586
|
+
this.cachedNodeLabel[node.id] = lines;
|
|
2349
2587
|
}
|
|
2350
|
-
const { lines } = getTextLines({
|
|
2351
|
-
context: this.context,
|
|
2352
|
-
maxWidth: nodeOptions.labelWidth,
|
|
2353
|
-
text: nodeOptions.label,
|
|
2354
|
-
textAlign: nodeOptions.labelAlign,
|
|
2355
|
-
textColor: nodeOptions.labelColor,
|
|
2356
|
-
textFont: nodeOptions.labelFont,
|
|
2357
|
-
textSize: nodeOptions.labelSize,
|
|
2358
|
-
textStyle: nodeOptions.labelStyle,
|
|
2359
|
-
textWeight: nodeOptions.labelWeight,
|
|
2360
|
-
});
|
|
2361
|
-
this.cachedNodeLabel[node.id] = lines;
|
|
2362
2588
|
}
|
|
2363
|
-
/** label in text shape */
|
|
2364
|
-
if (nodeOptions.shape === "text" && nodeOptions.label) {
|
|
2365
|
-
const textInfo = getTextLines({
|
|
2366
|
-
context: this.context,
|
|
2367
|
-
text: nodeOptions.label,
|
|
2368
|
-
textAlign: nodeOptions.labelAlign,
|
|
2369
|
-
textColor: nodeOptions.labelColor,
|
|
2370
|
-
textFont: nodeOptions.labelFont,
|
|
2371
|
-
textSize: labelSize,
|
|
2372
|
-
maxWidth: nodeOptions.labelWidth,
|
|
2373
|
-
textStyle: nodeOptions.labelStyle,
|
|
2374
|
-
textWeight: nodeOptions.textWeight,
|
|
2375
|
-
});
|
|
2376
|
-
const textNodeParameters = [textInfo.currentMaxSize, labelSize];
|
|
2377
|
-
const lines = textInfo.lines;
|
|
2378
|
-
const textSizeCoefficient = labelSize / textNodeParameters[1];
|
|
2379
|
-
const maxSize = textNodeParameters[0] * textSizeCoefficient;
|
|
2380
|
-
height =
|
|
2381
|
-
lines.length * labelSize +
|
|
2382
|
-
(lines.length - 1) * nodeOptions.labelGap +
|
|
2383
|
-
nodeOptions.labelYPadding;
|
|
2384
|
-
width = maxSize + nodeOptions.labelXPadding;
|
|
2385
|
-
this.cachedNodeLabel[node.id] = lines;
|
|
2386
|
-
}
|
|
2387
|
-
nodeOptions.width = node.visible === false ? 0 : width;
|
|
2388
|
-
nodeOptions.height = node.visible === false ? 0 : height;
|
|
2389
|
-
nodeOptions.radius = node.visible === false ? 0 : radius;
|
|
2390
|
-
nodeOptions.labelSize = labelSize;
|
|
2391
2589
|
/** text */
|
|
2392
|
-
if (nodeOptions.text) {
|
|
2590
|
+
if (nodeOptions.text && (types === true || (jsHelpers.isObject(types) && types.text))) {
|
|
2393
2591
|
this.context.font = `${nodeOptions.textStyle} normal ${nodeOptions.textWeight} ${nodeOptions.textSize}px ${nodeOptions.textFont}`;
|
|
2394
2592
|
this.context.fillStyle = nodeOptions.textColor;
|
|
2395
2593
|
this.context.textAlign = nodeOptions.textAlign;
|
|
@@ -2410,7 +2608,6 @@ function updateNodeCache() {
|
|
|
2410
2608
|
});
|
|
2411
2609
|
this.cachedNodeText[node.id] = lines;
|
|
2412
2610
|
}
|
|
2413
|
-
this.nodeOptionsCache[node.id] = nodeOptions;
|
|
2414
2611
|
}
|
|
2415
2612
|
}
|
|
2416
2613
|
|
|
@@ -2421,9 +2618,12 @@ function initZoom(currentZoom) {
|
|
|
2421
2618
|
.scaleExtent(this.graphSettings.zoomExtent)
|
|
2422
2619
|
.on("zoom", (event) => {
|
|
2423
2620
|
this.listeners.onZoom?.call?.(this, event);
|
|
2621
|
+
const oldTransform = this.areaTransform;
|
|
2424
2622
|
this.areaTransform = event.transform;
|
|
2425
|
-
|
|
2426
|
-
|
|
2623
|
+
if (this.areaTransform.k !== oldTransform.k) {
|
|
2624
|
+
updateLinkCache.call(this);
|
|
2625
|
+
updateNodeCache.call(this, true);
|
|
2626
|
+
}
|
|
2427
2627
|
if (!this.simulationWorking && !this.highlightWorking)
|
|
2428
2628
|
requestAnimationFrame(() => this.draw());
|
|
2429
2629
|
});
|
|
@@ -2531,20 +2731,38 @@ class GraphCanvas {
|
|
|
2531
2731
|
}
|
|
2532
2732
|
if (options.highlightSettings) {
|
|
2533
2733
|
this.highlightSettings = highlightSettingsGetter(options.highlightSettings, this.highlightSettings);
|
|
2534
|
-
if (clearCache) {
|
|
2535
|
-
this.clearCache([
|
|
2734
|
+
if (clearCache === true) {
|
|
2735
|
+
this.clearCache([
|
|
2736
|
+
GRAPH_CACHE_TYPE.NodeOptions,
|
|
2737
|
+
GRAPH_CACHE_TYPE.NodeText,
|
|
2738
|
+
GRAPH_CACHE_TYPE.NodeLabel,
|
|
2739
|
+
GRAPH_CACHE_TYPE.LinkOptions,
|
|
2740
|
+
]);
|
|
2741
|
+
}
|
|
2742
|
+
else {
|
|
2743
|
+
this.clearCache(clearCache);
|
|
2536
2744
|
}
|
|
2537
2745
|
}
|
|
2538
2746
|
if (options.linkSettings) {
|
|
2539
2747
|
this.linkSettings = linkSettingsGetter(options.linkSettings, this.linkSettings);
|
|
2540
2748
|
if (clearCache) {
|
|
2541
|
-
this.clearCache([
|
|
2749
|
+
this.clearCache([GRAPH_CACHE_TYPE.LinkOptions]);
|
|
2750
|
+
}
|
|
2751
|
+
else {
|
|
2752
|
+
this.clearCache(clearCache);
|
|
2542
2753
|
}
|
|
2543
2754
|
}
|
|
2544
2755
|
if (options.nodeSettings) {
|
|
2545
2756
|
this.nodeSettings = nodeSettingsGetter(options.nodeSettings, this.nodeSettings);
|
|
2546
2757
|
if (clearCache) {
|
|
2547
|
-
this.clearCache([
|
|
2758
|
+
this.clearCache([
|
|
2759
|
+
GRAPH_CACHE_TYPE.NodeOptions,
|
|
2760
|
+
GRAPH_CACHE_TYPE.NodeText,
|
|
2761
|
+
GRAPH_CACHE_TYPE.NodeLabel,
|
|
2762
|
+
]);
|
|
2763
|
+
}
|
|
2764
|
+
else {
|
|
2765
|
+
this.clearCache(clearCache);
|
|
2548
2766
|
}
|
|
2549
2767
|
initCollideForce.call(this, true);
|
|
2550
2768
|
}
|
|
@@ -2572,48 +2790,24 @@ class GraphCanvas {
|
|
|
2572
2790
|
throw new Error("couldn't create canvas context");
|
|
2573
2791
|
this.context.scale(this.dpi, this.dpi);
|
|
2574
2792
|
this.draw();
|
|
2575
|
-
// this.clearHTMLElements();
|
|
2576
|
-
// initArea.call<
|
|
2577
|
-
// GraphCanvas<NodeData, LinkData>,
|
|
2578
|
-
// Parameters<typeof initArea>,
|
|
2579
|
-
// ReturnType<typeof initArea>
|
|
2580
|
-
// >(this);
|
|
2581
|
-
// initDnd.call<
|
|
2582
|
-
// GraphCanvas<NodeData, LinkData>,
|
|
2583
|
-
// Parameters<typeof initDnd>,
|
|
2584
|
-
// ReturnType<typeof initDnd>
|
|
2585
|
-
// >(this);
|
|
2586
|
-
// initZoom.call<
|
|
2587
|
-
// GraphCanvas<NodeData, LinkData>,
|
|
2588
|
-
// Parameters<typeof initZoom>,
|
|
2589
|
-
// ReturnType<typeof initZoom>
|
|
2590
|
-
// >(this);
|
|
2591
|
-
// initResize.call<
|
|
2592
|
-
// GraphCanvas<NodeData, LinkData>,
|
|
2593
|
-
// Parameters<typeof initResize>,
|
|
2594
|
-
// ReturnType<typeof initResize>
|
|
2595
|
-
// >(this);
|
|
2596
|
-
// initPointer.call<
|
|
2597
|
-
// GraphCanvas<NodeData, LinkData>,
|
|
2598
|
-
// Parameters<typeof initPointer>,
|
|
2599
|
-
// ReturnType<typeof initPointer>
|
|
2600
|
-
// >(this);
|
|
2601
|
-
// this.draw();
|
|
2602
2793
|
}
|
|
2603
2794
|
clearCache(keys) {
|
|
2604
|
-
if (
|
|
2605
|
-
updateNodeCache.call(this);
|
|
2795
|
+
if (keys === true) {
|
|
2796
|
+
updateNodeCache.call(this, true);
|
|
2606
2797
|
updateLinkCache.call(this);
|
|
2607
2798
|
}
|
|
2608
|
-
else {
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
}
|
|
2799
|
+
else if (jsHelpers.isArray(keys)) {
|
|
2800
|
+
if (keys.some((k) => k === GRAPH_CACHE_TYPE.NodeText ||
|
|
2801
|
+
k === GRAPH_CACHE_TYPE.NodeLabel ||
|
|
2802
|
+
k === GRAPH_CACHE_TYPE.NodeOptions)) {
|
|
2803
|
+
updateNodeCache.call(this, {
|
|
2804
|
+
label: keys.includes(GRAPH_CACHE_TYPE.NodeLabel),
|
|
2805
|
+
options: keys.includes(GRAPH_CACHE_TYPE.NodeOptions),
|
|
2806
|
+
text: keys.includes(GRAPH_CACHE_TYPE.NodeOptions),
|
|
2807
|
+
});
|
|
2808
|
+
}
|
|
2809
|
+
if (keys.includes(GRAPH_CACHE_TYPE.LinkOptions)) {
|
|
2810
|
+
updateLinkCache.call(this);
|
|
2617
2811
|
}
|
|
2618
2812
|
}
|
|
2619
2813
|
}
|
|
@@ -2647,7 +2841,7 @@ class GraphCanvas {
|
|
|
2647
2841
|
}
|
|
2648
2842
|
this.clearHTMLElements();
|
|
2649
2843
|
this.clearState();
|
|
2650
|
-
this.clearCache();
|
|
2844
|
+
this.clearCache(true);
|
|
2651
2845
|
}
|
|
2652
2846
|
clearHTMLElements() {
|
|
2653
2847
|
this.root.replaceChildren();
|
|
@@ -2674,7 +2868,7 @@ class GraphCanvas {
|
|
|
2674
2868
|
}
|
|
2675
2869
|
updateData(alpha = 0.5, clearCache = true) {
|
|
2676
2870
|
if (clearCache) {
|
|
2677
|
-
this.clearCache();
|
|
2871
|
+
this.clearCache(clearCache);
|
|
2678
2872
|
}
|
|
2679
2873
|
if (this.simulation) {
|
|
2680
2874
|
initCollideForce.call(this, false);
|
|
@@ -2697,7 +2891,7 @@ class GraphCanvas {
|
|
|
2697
2891
|
}
|
|
2698
2892
|
init() {
|
|
2699
2893
|
initArea.call(this);
|
|
2700
|
-
updateNodeCache.call(this);
|
|
2894
|
+
updateNodeCache.call(this, true);
|
|
2701
2895
|
updateLinkCache.call(this);
|
|
2702
2896
|
initSimulation.call(this);
|
|
2703
2897
|
initDnd.call(this);
|
|
@@ -3884,6 +4078,7 @@ const NODE_OPTIONS_LABEL_CONTROLS = [
|
|
|
3884
4078
|
exports.COMMON_SETTINGS = COMMON_SETTINGS;
|
|
3885
4079
|
exports.FORCE_CONTROLS = FORCE_CONTROLS;
|
|
3886
4080
|
exports.FORCE_SETTINGS = FORCE_SETTINGS;
|
|
4081
|
+
exports.GRAPH_CACHE_TYPE = GRAPH_CACHE_TYPE;
|
|
3887
4082
|
exports.GRAPH_SETTINGS = GRAPH_SETTINGS;
|
|
3888
4083
|
exports.GraphCanvas = GraphCanvas;
|
|
3889
4084
|
exports.HIGHLIGHT_BY_LINK_FOR_ARROW_CONTROLS = HIGHLIGHT_BY_LINK_FOR_ARROW_CONTROLS;
|