@krainovsd/graph 0.7.0 → 0.8.1
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 +962 -178
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/esm/index.js +3 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/lib/draw-time.js +25 -0
- package/lib/esm/lib/draw-time.js.map +1 -0
- package/lib/esm/lib/get-controls-info.js +541 -0
- package/lib/esm/lib/get-controls-info.js.map +1 -0
- package/lib/esm/module/GraphCanvas/GraphCanvas.js +235 -80
- package/lib/esm/module/GraphCanvas/GraphCanvas.js.map +1 -1
- package/lib/esm/module/GraphCanvas/constants/settings.js +26 -7
- package/lib/esm/module/GraphCanvas/constants/settings.js.map +1 -1
- package/lib/esm/module/GraphCanvas/lib/settings/link-settings-getter.js +7 -4
- package/lib/esm/module/GraphCanvas/lib/settings/link-settings-getter.js.map +1 -1
- package/lib/esm/module/GraphCanvas/lib/settings/node-settings-getter.js +6 -5
- package/lib/esm/module/GraphCanvas/lib/settings/node-settings-getter.js.map +1 -1
- package/lib/esm/module/GraphCanvas/lib/utils/animation-by-progress.js +12 -0
- package/lib/esm/module/GraphCanvas/lib/utils/animation-by-progress.js.map +1 -0
- package/lib/esm/module/GraphCanvas/lib/utils/calculate-link-position-by-radius.js +2 -2
- package/lib/esm/module/GraphCanvas/lib/utils/calculate-link-position-by-radius.js.map +1 -1
- package/lib/esm/module/GraphCanvas/lib/utils/get-particle-position.js +24 -0
- package/lib/esm/module/GraphCanvas/lib/utils/get-particle-position.js.map +1 -0
- package/lib/esm/module/GraphCanvas/lib/utils/is-node-visible.js +14 -0
- package/lib/esm/module/GraphCanvas/lib/utils/is-node-visible.js.map +1 -0
- package/lib/esm/module/GraphCanvas/lib/utils/link-iteration-extractor.js +1 -0
- package/lib/esm/module/GraphCanvas/lib/utils/link-iteration-extractor.js.map +1 -1
- package/lib/esm/module/GraphCanvas/lib/utils/node-iteration-extractor.js +1 -0
- package/lib/esm/module/GraphCanvas/lib/utils/node-iteration-extractor.js.map +1 -1
- package/lib/index.d.ts +72 -3
- package/package.json +4 -2
package/lib/cjs/index.cjs
CHANGED
|
@@ -87,95 +87,6 @@ function rgbAnimationByProgress(start, end, progress) {
|
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
const FORCE_SETTINGS = {
|
|
91
|
-
centerPosition: {},
|
|
92
|
-
centerStrength: 1,
|
|
93
|
-
collideStrength: 0.1,
|
|
94
|
-
collideAdditionalRadius: 4,
|
|
95
|
-
collideIterations: 2,
|
|
96
|
-
collideOffMax: { links: 0, nodes: 0 },
|
|
97
|
-
collideOn: true,
|
|
98
|
-
chargeStrength: -40,
|
|
99
|
-
chargeDistanceMax: Infinity,
|
|
100
|
-
chargeDistanceMin: 1,
|
|
101
|
-
xForce: 0,
|
|
102
|
-
xStrength: 0.1,
|
|
103
|
-
yForce: 0,
|
|
104
|
-
yStrength: 0.1,
|
|
105
|
-
linkDistance: 30,
|
|
106
|
-
linkIterations: 1,
|
|
107
|
-
linkStrength: 1,
|
|
108
|
-
collideRadius: null,
|
|
109
|
-
};
|
|
110
|
-
const GRAPH_SETTINGS = {
|
|
111
|
-
zoomExtent: [0.1, 20],
|
|
112
|
-
translateExtent: [[], []],
|
|
113
|
-
translateExtentEnable: true,
|
|
114
|
-
translateExtentCoefficient: [1.2, 1.1],
|
|
115
|
-
highlightSizingAdditional: 0.5,
|
|
116
|
-
highlightColorFadingMin: 0.15,
|
|
117
|
-
highlightTextShiftXAdditional: 0,
|
|
118
|
-
highlightTextShiftYAdditional: 2,
|
|
119
|
-
highlightTextSizingAdditional: 1,
|
|
120
|
-
highlightTextWeightAdditional: 0,
|
|
121
|
-
highlightTextWidthAdditional: 10,
|
|
122
|
-
highlightOnlyRoot: true,
|
|
123
|
-
stickAfterDrag: false,
|
|
124
|
-
highlightByHover: false,
|
|
125
|
-
highlightLinkFadingMin: 0.21,
|
|
126
|
-
highlightFadingMin: 0.21,
|
|
127
|
-
highlightTextFadingMin: 0.21,
|
|
128
|
-
highlightDownStep: 0.2,
|
|
129
|
-
highlightUpStep: 0.2,
|
|
130
|
-
dragPlaceCoefficient: dragPlaceCoefficientGetter,
|
|
131
|
-
nodeRadiusInitial: 4,
|
|
132
|
-
nodeRadiusCoefficient: 5,
|
|
133
|
-
nodeRadiusFactor: 1,
|
|
134
|
-
nodeRadiusFlexible: true,
|
|
135
|
-
zoomInitial: null,
|
|
136
|
-
};
|
|
137
|
-
const NODE_SETTINGS = {
|
|
138
|
-
alpha: 1,
|
|
139
|
-
textAlpha: 1,
|
|
140
|
-
borderColor: "#000000FF",
|
|
141
|
-
borderWidth: 0.1,
|
|
142
|
-
textWidth: 20,
|
|
143
|
-
textShiftX: 0,
|
|
144
|
-
textFont: "Arial",
|
|
145
|
-
textAlign: "center",
|
|
146
|
-
textColor: "#333",
|
|
147
|
-
width: 1,
|
|
148
|
-
radius: 4,
|
|
149
|
-
textStyle: "normal",
|
|
150
|
-
textWeight: 500,
|
|
151
|
-
textGap: 1,
|
|
152
|
-
highlightFading: false,
|
|
153
|
-
highlightColor: true,
|
|
154
|
-
highlightSizing: true,
|
|
155
|
-
highlightTextFading: true,
|
|
156
|
-
highlightTextSizing: true,
|
|
157
|
-
};
|
|
158
|
-
const LINK_SETTINGS = {
|
|
159
|
-
alpha: 1,
|
|
160
|
-
highlightFading: true,
|
|
161
|
-
pretty: true,
|
|
162
|
-
};
|
|
163
|
-
const COMMON_SETTINGS = {
|
|
164
|
-
linkColorZoomFar: "#999",
|
|
165
|
-
linkColorZoomNear: "#000000FF",
|
|
166
|
-
linkWidthZoomFar: 1,
|
|
167
|
-
linkWidthZoomNear: 0.1,
|
|
168
|
-
linkWidthZoomBorder: 1,
|
|
169
|
-
linkColorZoomBorder: 1,
|
|
170
|
-
nodeTextScaleMin: 1.5,
|
|
171
|
-
nodeTextScaleMax: 20,
|
|
172
|
-
nodeTextSizeMin: 1.5,
|
|
173
|
-
nodeTextSizeMax: 3.5,
|
|
174
|
-
nodeTextShiftYMin: 2.5,
|
|
175
|
-
nodeTextShiftYMax: 4,
|
|
176
|
-
nodeTextChangeStepCount: 200,
|
|
177
|
-
};
|
|
178
|
-
|
|
179
90
|
function forceSettingsGetter(settings, prevSettings) {
|
|
180
91
|
return {
|
|
181
92
|
...(prevSettings ?? FORCE_SETTINGS),
|
|
@@ -190,17 +101,20 @@ function graphSettingsGetter(settings, prevSettings) {
|
|
|
190
101
|
};
|
|
191
102
|
}
|
|
192
103
|
|
|
193
|
-
function linkSettingsGetter(settings) {
|
|
194
|
-
return {
|
|
104
|
+
function linkSettingsGetter(settings, prevSettings) {
|
|
105
|
+
return { ...(prevSettings ?? LINK_SETTINGS), ...settings };
|
|
195
106
|
}
|
|
196
107
|
function linkOptionsGetter(_, __, ___, state) {
|
|
197
108
|
return {
|
|
198
|
-
...
|
|
109
|
+
...LINK_OPTIONS,
|
|
199
110
|
drawExtraLink: null,
|
|
200
111
|
drawLink: null,
|
|
201
112
|
color: state?.areaTransform && state?.areaTransform.k > COMMON_SETTINGS.linkColorZoomBorder
|
|
202
113
|
? COMMON_SETTINGS.linkColorZoomNear
|
|
203
114
|
: COMMON_SETTINGS.linkColorZoomFar,
|
|
115
|
+
arrowColor: state?.areaTransform && state?.areaTransform.k > COMMON_SETTINGS.linkColorZoomBorder
|
|
116
|
+
? COMMON_SETTINGS.linkColorZoomNear
|
|
117
|
+
: COMMON_SETTINGS.linkColorZoomFar,
|
|
204
118
|
width: state?.areaTransform && state?.areaTransform.k > COMMON_SETTINGS.linkWidthZoomBorder
|
|
205
119
|
? COMMON_SETTINGS.linkWidthZoomNear
|
|
206
120
|
: COMMON_SETTINGS.linkWidthZoomFar,
|
|
@@ -211,17 +125,18 @@ function listenersGetter(settings) {
|
|
|
211
125
|
return settings ?? {};
|
|
212
126
|
}
|
|
213
127
|
|
|
214
|
-
function nodeSettingsGetter(settings) {
|
|
128
|
+
function nodeSettingsGetter(settings, prevNodeSettings) {
|
|
215
129
|
return {
|
|
216
|
-
|
|
217
|
-
|
|
130
|
+
...(prevNodeSettings ?? NODE_SETTINGS),
|
|
131
|
+
idGetter: nodeIdGetter,
|
|
132
|
+
...settings,
|
|
218
133
|
};
|
|
219
134
|
}
|
|
220
135
|
const color = colorGetter();
|
|
221
136
|
function nodeOptionsGetter(node, _, __, state) {
|
|
222
137
|
const { textShiftY, textSize } = nodeTextSizeGetter(state?.areaTransform);
|
|
223
138
|
return {
|
|
224
|
-
...
|
|
139
|
+
...NODE_OPTIONS,
|
|
225
140
|
nodeDraw: null,
|
|
226
141
|
nodeExtraDraw: null,
|
|
227
142
|
textDraw: null,
|
|
@@ -410,7 +325,7 @@ function drawText({ context, id, textAlign, textColor, textFont, textStyle, text
|
|
|
410
325
|
});
|
|
411
326
|
}
|
|
412
327
|
|
|
413
|
-
function calculateLinkPositionByRadius(link) {
|
|
328
|
+
function calculateLinkPositionByRadius(link, arrowSize = 0) {
|
|
414
329
|
const source = link.source;
|
|
415
330
|
const target = link.target;
|
|
416
331
|
if (typeof source != "object" || typeof target != "object")
|
|
@@ -419,7 +334,7 @@ function calculateLinkPositionByRadius(link) {
|
|
|
419
334
|
const dy = (target.y ?? 0) - (source.y ?? 0);
|
|
420
335
|
const dr = Math.sqrt(dx * dx + dy * dy);
|
|
421
336
|
const sourceRadius = source._radius ?? 0;
|
|
422
|
-
const targetRadius = target._radius ?? 0;
|
|
337
|
+
const targetRadius = (target._radius ?? 0) + (arrowSize > 0 ? arrowSize * 0.85 : 0);
|
|
423
338
|
return {
|
|
424
339
|
x1: (source.x ?? 0) + (dx * sourceRadius) / dr,
|
|
425
340
|
y1: (source.y ?? 0) + (dy * sourceRadius) / dr,
|
|
@@ -428,10 +343,723 @@ function calculateLinkPositionByRadius(link) {
|
|
|
428
343
|
};
|
|
429
344
|
}
|
|
430
345
|
|
|
346
|
+
function animationByProgress(initial, additional, progress) {
|
|
347
|
+
const max = initial + additional;
|
|
348
|
+
let current = initial + (max - initial) * progress;
|
|
349
|
+
if (current > max)
|
|
350
|
+
current = max;
|
|
351
|
+
if (current < initial)
|
|
352
|
+
current = initial;
|
|
353
|
+
return current;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const ADDITIONAL_VIEWPORT = 10;
|
|
357
|
+
function isNodeVisible(opts) {
|
|
358
|
+
const left = -opts.transform.x / opts.transform.k;
|
|
359
|
+
const right = (opts.width - opts.transform.x) / opts.transform.k;
|
|
360
|
+
const top = -opts.transform.y / opts.transform.k;
|
|
361
|
+
const bottom = (opts.height - opts.transform.y) / opts.transform.k;
|
|
362
|
+
return (left < opts.x + opts.radius + ADDITIONAL_VIEWPORT &&
|
|
363
|
+
opts.x - opts.radius - ADDITIONAL_VIEWPORT < right &&
|
|
364
|
+
top < opts.y + opts.radius + ADDITIONAL_VIEWPORT &&
|
|
365
|
+
opts.y - opts.radius - ADDITIONAL_VIEWPORT < bottom);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function getParticlePosition(opts) {
|
|
369
|
+
if (opts.particle.wait > 0) {
|
|
370
|
+
opts.particle.wait--;
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
const remainingSteps = opts.totalSteps - opts.particle.step;
|
|
374
|
+
const progress = opts.particle.step / opts.totalSteps;
|
|
375
|
+
if (remainingSteps === 0) {
|
|
376
|
+
opts.particle.x = opts.xEnd;
|
|
377
|
+
opts.particle.y = opts.yEnd;
|
|
378
|
+
opts.particle.step = 0;
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
const dx = opts.xEnd - opts.xStart;
|
|
382
|
+
const dy = opts.yEnd - opts.yStart;
|
|
383
|
+
const newX = opts.xStart + dx * progress;
|
|
384
|
+
const newY = opts.yStart + dy * progress;
|
|
385
|
+
opts.particle.x = newX;
|
|
386
|
+
opts.particle.y = newY;
|
|
387
|
+
opts.particle.step++;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const FORCE_SETTINGS = {
|
|
391
|
+
centerPosition: {},
|
|
392
|
+
centerStrength: 1,
|
|
393
|
+
collideStrength: 0.1,
|
|
394
|
+
collideAdditionalRadius: 4,
|
|
395
|
+
collideIterations: 2,
|
|
396
|
+
collideOffMax: { links: 0, nodes: 0 },
|
|
397
|
+
collideOn: true,
|
|
398
|
+
chargeStrength: -40,
|
|
399
|
+
chargeDistanceMax: Infinity,
|
|
400
|
+
chargeDistanceMin: 1,
|
|
401
|
+
xForce: 0,
|
|
402
|
+
xStrength: 0.1,
|
|
403
|
+
yForce: 0,
|
|
404
|
+
yStrength: 0.1,
|
|
405
|
+
linkDistance: 30,
|
|
406
|
+
linkIterations: 1,
|
|
407
|
+
linkStrength: 1,
|
|
408
|
+
collideRadius: null,
|
|
409
|
+
};
|
|
410
|
+
const GRAPH_SETTINGS = {
|
|
411
|
+
zoomExtent: [0.3, 10],
|
|
412
|
+
translateExtent: [[], []],
|
|
413
|
+
translateExtentEnable: true,
|
|
414
|
+
translateExtentCoefficient: [3, 3],
|
|
415
|
+
highlightSizingAdditional: 0.5,
|
|
416
|
+
highlightColorFadingMin: 0.15,
|
|
417
|
+
highlightTextShiftXAdditional: 0,
|
|
418
|
+
highlightTextShiftYAdditional: 2,
|
|
419
|
+
highlightTextSizingAdditional: 1,
|
|
420
|
+
highlightTextWeightAdditional: 0,
|
|
421
|
+
highlightTextWidthAdditional: 10,
|
|
422
|
+
highlightOnlyRoot: true,
|
|
423
|
+
stickAfterDrag: false,
|
|
424
|
+
highlightByHover: true,
|
|
425
|
+
highlightLinkFadingMin: 0.21,
|
|
426
|
+
highlightFadingMin: 0.21,
|
|
427
|
+
highlightTextFadingMin: 0.21,
|
|
428
|
+
highlightArrowFadingMin: 0.21,
|
|
429
|
+
highlightDownStep: 0.2,
|
|
430
|
+
highlightUpStep: 0.2,
|
|
431
|
+
dragPlaceCoefficient: dragPlaceCoefficientGetter,
|
|
432
|
+
nodeRadiusInitial: 4,
|
|
433
|
+
nodeRadiusCoefficient: 5,
|
|
434
|
+
nodeRadiusFactor: 1,
|
|
435
|
+
nodeRadiusFlexible: true,
|
|
436
|
+
zoomInitial: null,
|
|
437
|
+
showDrawTime: true,
|
|
438
|
+
showDrawTimeEveryTick: false,
|
|
439
|
+
};
|
|
440
|
+
const NODE_SETTINGS = {
|
|
441
|
+
cache: false,
|
|
442
|
+
};
|
|
443
|
+
const NODE_OPTIONS = {
|
|
444
|
+
alpha: 1,
|
|
445
|
+
textAlpha: 1,
|
|
446
|
+
borderColor: "#000000FF",
|
|
447
|
+
borderWidth: 0.1,
|
|
448
|
+
textWidth: 20,
|
|
449
|
+
textShiftX: 0,
|
|
450
|
+
textFont: "Arial",
|
|
451
|
+
textAlign: "center",
|
|
452
|
+
textColor: "#333",
|
|
453
|
+
radius: 4,
|
|
454
|
+
textStyle: "normal",
|
|
455
|
+
textWeight: 500,
|
|
456
|
+
textGap: 1,
|
|
457
|
+
highlightFading: true,
|
|
458
|
+
highlightColor: false,
|
|
459
|
+
highlightSizing: true,
|
|
460
|
+
highlightTextFading: true,
|
|
461
|
+
highlightTextSizing: true,
|
|
462
|
+
};
|
|
463
|
+
const LINK_SETTINGS = {
|
|
464
|
+
cache: false,
|
|
465
|
+
particles: true,
|
|
466
|
+
};
|
|
467
|
+
const LINK_OPTIONS = {
|
|
468
|
+
alpha: 1,
|
|
469
|
+
highlightFading: true,
|
|
470
|
+
pretty: true,
|
|
471
|
+
arrow: true,
|
|
472
|
+
arrowAlpha: 1,
|
|
473
|
+
arrowSize: 2,
|
|
474
|
+
arrowHighlightFading: true,
|
|
475
|
+
arrowReverseAppear: true,
|
|
476
|
+
particleAlpha: 1,
|
|
477
|
+
particleColor: "#000000FF",
|
|
478
|
+
particleCount: 2,
|
|
479
|
+
particleRadius: 0.5,
|
|
480
|
+
particleSteps: 60,
|
|
481
|
+
};
|
|
482
|
+
const COMMON_SETTINGS = {
|
|
483
|
+
linkColorZoomFar: "#999",
|
|
484
|
+
linkColorZoomNear: "#000000FF",
|
|
485
|
+
linkWidthZoomFar: 1,
|
|
486
|
+
linkWidthZoomNear: 0.1,
|
|
487
|
+
linkWidthZoomBorder: 1,
|
|
488
|
+
linkColorZoomBorder: 1,
|
|
489
|
+
nodeTextScaleMin: 1.5,
|
|
490
|
+
nodeTextScaleMax: 20,
|
|
491
|
+
nodeTextSizeMin: 1.5,
|
|
492
|
+
nodeTextSizeMax: 3.5,
|
|
493
|
+
nodeTextShiftYMin: 2.5,
|
|
494
|
+
nodeTextShiftYMax: 4,
|
|
495
|
+
nodeTextChangeStepCount: 200,
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
function getForceControls(keys) {
|
|
499
|
+
const FORCE_CONTROLS = [
|
|
500
|
+
{
|
|
501
|
+
id: "centerStrength",
|
|
502
|
+
initialValue: FORCE_SETTINGS.centerStrength,
|
|
503
|
+
label: "Граница центра",
|
|
504
|
+
max: 1,
|
|
505
|
+
min: 0,
|
|
506
|
+
step: 0.01,
|
|
507
|
+
type: "range",
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
id: "collideStrength",
|
|
511
|
+
initialValue: FORCE_SETTINGS.collideStrength,
|
|
512
|
+
label: "Сила отталкивания",
|
|
513
|
+
max: 1,
|
|
514
|
+
min: 0,
|
|
515
|
+
step: 0.01,
|
|
516
|
+
type: "range",
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
id: "collideAdditionalRadius",
|
|
520
|
+
initialValue: FORCE_SETTINGS.collideAdditionalRadius,
|
|
521
|
+
label: "Радиус отталкивания",
|
|
522
|
+
max: 300,
|
|
523
|
+
min: 0,
|
|
524
|
+
step: 0.1,
|
|
525
|
+
type: "range",
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
id: "collideIterations",
|
|
529
|
+
initialValue: FORCE_SETTINGS.collideIterations,
|
|
530
|
+
label: "Итерации отталкивания",
|
|
531
|
+
max: 10,
|
|
532
|
+
min: 0,
|
|
533
|
+
step: 1,
|
|
534
|
+
type: "range",
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
id: "chargeStrength",
|
|
538
|
+
initialValue: FORCE_SETTINGS.chargeStrength ,
|
|
539
|
+
label: "Гравитация",
|
|
540
|
+
max: 0,
|
|
541
|
+
min: -300,
|
|
542
|
+
step: 0.1,
|
|
543
|
+
type: "range",
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
type: "range",
|
|
547
|
+
id: "xForce",
|
|
548
|
+
min: 0,
|
|
549
|
+
max: 1,
|
|
550
|
+
step: 0.01,
|
|
551
|
+
label: "Граница X",
|
|
552
|
+
initialValue: FORCE_SETTINGS.xForce ,
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
type: "range",
|
|
556
|
+
id: "yForce",
|
|
557
|
+
min: 0,
|
|
558
|
+
max: 1,
|
|
559
|
+
step: 0.01,
|
|
560
|
+
label: "Граница Y",
|
|
561
|
+
initialValue: FORCE_SETTINGS.yForce ,
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
type: "range",
|
|
565
|
+
id: "xStrength",
|
|
566
|
+
min: 0,
|
|
567
|
+
max: 1,
|
|
568
|
+
step: 0.01,
|
|
569
|
+
label: "Гравитация X",
|
|
570
|
+
initialValue: FORCE_SETTINGS.xStrength ,
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
type: "range",
|
|
574
|
+
id: "yStrength",
|
|
575
|
+
min: 0,
|
|
576
|
+
max: 1,
|
|
577
|
+
step: 0.01,
|
|
578
|
+
label: "Гравитация Y",
|
|
579
|
+
initialValue: FORCE_SETTINGS.yStrength ,
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
type: "range",
|
|
583
|
+
id: "linkStrength",
|
|
584
|
+
min: 0,
|
|
585
|
+
max: 1,
|
|
586
|
+
step: 0.01,
|
|
587
|
+
label: "Натяжение связей",
|
|
588
|
+
initialValue: FORCE_SETTINGS.linkStrength ,
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
type: "range",
|
|
592
|
+
id: "linkDistance",
|
|
593
|
+
min: 0,
|
|
594
|
+
max: 300,
|
|
595
|
+
step: 0.1,
|
|
596
|
+
label: "Расстояние связей",
|
|
597
|
+
initialValue: FORCE_SETTINGS.linkDistance ,
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
id: "collideOn",
|
|
601
|
+
type: "checkbox",
|
|
602
|
+
initialValue: FORCE_SETTINGS.collideOn,
|
|
603
|
+
label: "Отталкивание",
|
|
604
|
+
},
|
|
605
|
+
];
|
|
606
|
+
return keys ? FORCE_CONTROLS.filter((control) => keys.includes(control.id)) : FORCE_CONTROLS;
|
|
607
|
+
}
|
|
608
|
+
function getGraphControls(keys) {
|
|
609
|
+
const GRAPH_CONTROLS = [
|
|
610
|
+
{
|
|
611
|
+
id: "highlightSizingAdditional",
|
|
612
|
+
initialValue: GRAPH_SETTINGS.highlightSizingAdditional,
|
|
613
|
+
max: 10,
|
|
614
|
+
min: 0.1,
|
|
615
|
+
step: 0.01,
|
|
616
|
+
type: "range",
|
|
617
|
+
label: "Дополнительный размер при анимации",
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
id: "highlightColorFadingMin",
|
|
621
|
+
initialValue: GRAPH_SETTINGS.highlightColorFadingMin,
|
|
622
|
+
max: 1,
|
|
623
|
+
min: 0.01,
|
|
624
|
+
step: 0.01,
|
|
625
|
+
type: "range",
|
|
626
|
+
label: "Граница затухания цвета",
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
id: "highlightTextShiftXAdditional",
|
|
630
|
+
initialValue: GRAPH_SETTINGS.highlightTextShiftXAdditional,
|
|
631
|
+
max: 50,
|
|
632
|
+
min: 0,
|
|
633
|
+
step: 0.1,
|
|
634
|
+
type: "range",
|
|
635
|
+
label: "Смещение текста по X при анимации",
|
|
636
|
+
},
|
|
637
|
+
{
|
|
638
|
+
id: "highlightTextShiftYAdditional",
|
|
639
|
+
initialValue: GRAPH_SETTINGS.highlightTextShiftYAdditional,
|
|
640
|
+
max: 50,
|
|
641
|
+
min: 0,
|
|
642
|
+
step: 0.1,
|
|
643
|
+
type: "range",
|
|
644
|
+
label: "Смещение текста по Y при анимации",
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
id: "highlightTextSizingAdditional",
|
|
648
|
+
initialValue: GRAPH_SETTINGS.highlightTextSizingAdditional,
|
|
649
|
+
max: 10,
|
|
650
|
+
min: 0.1,
|
|
651
|
+
step: 0.1,
|
|
652
|
+
type: "range",
|
|
653
|
+
label: "Увеличение текста при анимации",
|
|
654
|
+
},
|
|
655
|
+
{
|
|
656
|
+
id: "highlightTextWeightAdditional",
|
|
657
|
+
initialValue: GRAPH_SETTINGS.highlightTextWeightAdditional,
|
|
658
|
+
max: 1000,
|
|
659
|
+
min: 0,
|
|
660
|
+
step: 100,
|
|
661
|
+
type: "range",
|
|
662
|
+
label: "Увеличение жирности текста при анимации",
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
id: "highlightTextWidthAdditional",
|
|
666
|
+
initialValue: GRAPH_SETTINGS.highlightTextWidthAdditional,
|
|
667
|
+
max: 100,
|
|
668
|
+
min: 0,
|
|
669
|
+
step: 0.1,
|
|
670
|
+
type: "range",
|
|
671
|
+
label: "Увеличение ширины текста при анимации",
|
|
672
|
+
},
|
|
673
|
+
{
|
|
674
|
+
id: "highlightTextFadingMin",
|
|
675
|
+
initialValue: GRAPH_SETTINGS.highlightTextFadingMin,
|
|
676
|
+
max: 1,
|
|
677
|
+
min: 0,
|
|
678
|
+
step: 0.01,
|
|
679
|
+
type: "range",
|
|
680
|
+
label: "Граница затухания текста при анимации",
|
|
681
|
+
},
|
|
682
|
+
{
|
|
683
|
+
id: "highlightLinkFadingMin",
|
|
684
|
+
initialValue: GRAPH_SETTINGS.highlightLinkFadingMin,
|
|
685
|
+
max: 1,
|
|
686
|
+
min: 0,
|
|
687
|
+
step: 0.01,
|
|
688
|
+
type: "range",
|
|
689
|
+
label: "Граница затухания связи при анимации",
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
id: "highlightFadingMin",
|
|
693
|
+
initialValue: GRAPH_SETTINGS.highlightFadingMin,
|
|
694
|
+
max: 1,
|
|
695
|
+
min: 0,
|
|
696
|
+
step: 0.01,
|
|
697
|
+
type: "range",
|
|
698
|
+
label: "Граница затухания ноды при анимации",
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
id: "highlightArrowFadingMin",
|
|
702
|
+
initialValue: GRAPH_SETTINGS.highlightArrowFadingMin,
|
|
703
|
+
max: 1,
|
|
704
|
+
min: 0,
|
|
705
|
+
step: 0.01,
|
|
706
|
+
type: "range",
|
|
707
|
+
label: "Граница затухания стрелки при анимации",
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
id: "highlightDownStep",
|
|
711
|
+
initialValue: GRAPH_SETTINGS.highlightDownStep,
|
|
712
|
+
max: 1,
|
|
713
|
+
min: 0.01,
|
|
714
|
+
step: 0.01,
|
|
715
|
+
type: "range",
|
|
716
|
+
label: "Скорость отмены анимации",
|
|
717
|
+
},
|
|
718
|
+
{
|
|
719
|
+
id: "highlightUpStep",
|
|
720
|
+
initialValue: GRAPH_SETTINGS.highlightUpStep,
|
|
721
|
+
max: 1,
|
|
722
|
+
min: 0.01,
|
|
723
|
+
step: 0.01,
|
|
724
|
+
type: "range",
|
|
725
|
+
label: "Скорость применения анимации",
|
|
726
|
+
},
|
|
727
|
+
{
|
|
728
|
+
id: "nodeRadiusInitial",
|
|
729
|
+
initialValue: GRAPH_SETTINGS.nodeRadiusInitial,
|
|
730
|
+
max: 50,
|
|
731
|
+
min: 0.1,
|
|
732
|
+
step: 0.1,
|
|
733
|
+
type: "range",
|
|
734
|
+
label: "Изначальный радиус ноды",
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
id: "nodeRadiusCoefficient",
|
|
738
|
+
initialValue: GRAPH_SETTINGS.nodeRadiusCoefficient,
|
|
739
|
+
max: 100,
|
|
740
|
+
min: 0.1,
|
|
741
|
+
step: 0.1,
|
|
742
|
+
type: "range",
|
|
743
|
+
label: "Количество связей для увеличения радиуса",
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
id: "nodeRadiusFactor",
|
|
747
|
+
initialValue: GRAPH_SETTINGS.nodeRadiusFactor,
|
|
748
|
+
max: 50,
|
|
749
|
+
min: 0.1,
|
|
750
|
+
step: 0.1,
|
|
751
|
+
type: "range",
|
|
752
|
+
label: "Коэффициент увеличения радиуса",
|
|
753
|
+
},
|
|
754
|
+
{
|
|
755
|
+
id: "highlightOnlyRoot",
|
|
756
|
+
type: "checkbox",
|
|
757
|
+
initialValue: GRAPH_SETTINGS.highlightOnlyRoot,
|
|
758
|
+
label: "Дополнительная анимация только главное цели",
|
|
759
|
+
},
|
|
760
|
+
{
|
|
761
|
+
id: "stickAfterDrag",
|
|
762
|
+
type: "checkbox",
|
|
763
|
+
initialValue: GRAPH_SETTINGS.stickAfterDrag,
|
|
764
|
+
label: "Фиксировании ноды после перетаскивания",
|
|
765
|
+
},
|
|
766
|
+
{
|
|
767
|
+
id: "highlightByHover",
|
|
768
|
+
type: "checkbox",
|
|
769
|
+
initialValue: GRAPH_SETTINGS.highlightByHover,
|
|
770
|
+
label: "Анимации при наведении",
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
id: "nodeRadiusFlexible",
|
|
774
|
+
type: "checkbox",
|
|
775
|
+
initialValue: GRAPH_SETTINGS.nodeRadiusFlexible,
|
|
776
|
+
label: "Гибкий радиус ноды",
|
|
777
|
+
},
|
|
778
|
+
];
|
|
779
|
+
return keys ? GRAPH_CONTROLS.filter((control) => keys.includes(control.id)) : GRAPH_CONTROLS;
|
|
780
|
+
}
|
|
781
|
+
function getNodeControls(keys) {
|
|
782
|
+
const NODE_CONTROLS = [
|
|
783
|
+
{
|
|
784
|
+
id: "alpha",
|
|
785
|
+
type: "range",
|
|
786
|
+
max: 1,
|
|
787
|
+
min: 0,
|
|
788
|
+
step: 0.1,
|
|
789
|
+
label: "Прозрачность",
|
|
790
|
+
initialValue: NODE_OPTIONS.alpha,
|
|
791
|
+
},
|
|
792
|
+
{
|
|
793
|
+
id: "radius",
|
|
794
|
+
type: "range",
|
|
795
|
+
max: 50,
|
|
796
|
+
min: 1,
|
|
797
|
+
step: 1,
|
|
798
|
+
label: "Радиус",
|
|
799
|
+
initialValue: NODE_OPTIONS.radius,
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
id: "borderWidth",
|
|
803
|
+
type: "range",
|
|
804
|
+
max: 5,
|
|
805
|
+
min: 0,
|
|
806
|
+
step: 0.1,
|
|
807
|
+
label: "Толщина границы",
|
|
808
|
+
initialValue: NODE_OPTIONS.borderWidth,
|
|
809
|
+
},
|
|
810
|
+
{
|
|
811
|
+
id: "borderColor",
|
|
812
|
+
type: "color",
|
|
813
|
+
initialValue: "#000000FF",
|
|
814
|
+
label: "Цвет границы",
|
|
815
|
+
},
|
|
816
|
+
{
|
|
817
|
+
id: "color",
|
|
818
|
+
type: "color",
|
|
819
|
+
initialValue: "#000000FF",
|
|
820
|
+
label: "Цвет",
|
|
821
|
+
},
|
|
822
|
+
{
|
|
823
|
+
id: "textAlpha",
|
|
824
|
+
type: "range",
|
|
825
|
+
max: 1,
|
|
826
|
+
min: 0,
|
|
827
|
+
step: 0.1,
|
|
828
|
+
label: "Прозрачность текста",
|
|
829
|
+
initialValue: NODE_OPTIONS.textAlpha,
|
|
830
|
+
},
|
|
831
|
+
{
|
|
832
|
+
id: "textWidth",
|
|
833
|
+
type: "range",
|
|
834
|
+
max: 200,
|
|
835
|
+
min: 5,
|
|
836
|
+
step: 1,
|
|
837
|
+
label: "Ширина текста",
|
|
838
|
+
initialValue: NODE_OPTIONS.textWidth,
|
|
839
|
+
},
|
|
840
|
+
{
|
|
841
|
+
id: "textShiftX",
|
|
842
|
+
type: "range",
|
|
843
|
+
max: 100,
|
|
844
|
+
min: 0,
|
|
845
|
+
step: 0.1,
|
|
846
|
+
label: "Смещение X текста",
|
|
847
|
+
initialValue: NODE_OPTIONS.textShiftX,
|
|
848
|
+
},
|
|
849
|
+
{
|
|
850
|
+
id: "textShiftY",
|
|
851
|
+
type: "range",
|
|
852
|
+
max: 100,
|
|
853
|
+
min: 0,
|
|
854
|
+
step: 0.1,
|
|
855
|
+
label: "Смещение Y текста",
|
|
856
|
+
initialValue: 4,
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
id: "textWeight",
|
|
860
|
+
type: "range",
|
|
861
|
+
max: 1000,
|
|
862
|
+
min: 100,
|
|
863
|
+
step: 100,
|
|
864
|
+
label: "Жирность текста",
|
|
865
|
+
initialValue: NODE_OPTIONS.textWeight,
|
|
866
|
+
},
|
|
867
|
+
{
|
|
868
|
+
id: "textGap",
|
|
869
|
+
type: "range",
|
|
870
|
+
max: 30,
|
|
871
|
+
min: 0,
|
|
872
|
+
step: 0.1,
|
|
873
|
+
label: "Расстояние между строками",
|
|
874
|
+
initialValue: NODE_OPTIONS.textGap,
|
|
875
|
+
},
|
|
876
|
+
{
|
|
877
|
+
id: "highlightFading",
|
|
878
|
+
type: "checkbox",
|
|
879
|
+
initialValue: NODE_OPTIONS.highlightFading,
|
|
880
|
+
label: "Анимация затухания",
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
id: "highlightColor",
|
|
884
|
+
type: "checkbox",
|
|
885
|
+
initialValue: NODE_OPTIONS.highlightColor,
|
|
886
|
+
label: "Анимация затухания цвета",
|
|
887
|
+
},
|
|
888
|
+
{
|
|
889
|
+
id: "highlightSizing",
|
|
890
|
+
type: "checkbox",
|
|
891
|
+
initialValue: NODE_OPTIONS.highlightSizing,
|
|
892
|
+
label: "Анимация размера",
|
|
893
|
+
},
|
|
894
|
+
{
|
|
895
|
+
id: "highlightTextFading",
|
|
896
|
+
type: "checkbox",
|
|
897
|
+
initialValue: NODE_OPTIONS.highlightTextFading,
|
|
898
|
+
label: "Анимация затухания текста",
|
|
899
|
+
},
|
|
900
|
+
{
|
|
901
|
+
id: "highlightTextSizing",
|
|
902
|
+
type: "checkbox",
|
|
903
|
+
initialValue: NODE_OPTIONS.highlightTextSizing,
|
|
904
|
+
label: "Анимация размера текста",
|
|
905
|
+
},
|
|
906
|
+
];
|
|
907
|
+
return keys ? NODE_CONTROLS.filter((control) => keys.includes(control.id)) : NODE_CONTROLS;
|
|
908
|
+
}
|
|
909
|
+
function getLinkControls(keys) {
|
|
910
|
+
const LINK_CONTROLS = [
|
|
911
|
+
{
|
|
912
|
+
id: "alpha",
|
|
913
|
+
type: "range",
|
|
914
|
+
max: 1,
|
|
915
|
+
min: 0,
|
|
916
|
+
step: 0.1,
|
|
917
|
+
label: "Прозрачность",
|
|
918
|
+
initialValue: LINK_OPTIONS.alpha,
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
id: "width",
|
|
922
|
+
type: "range",
|
|
923
|
+
max: 10,
|
|
924
|
+
min: 0.1,
|
|
925
|
+
step: 0.1,
|
|
926
|
+
label: "Толщина",
|
|
927
|
+
initialValue: 0.1,
|
|
928
|
+
},
|
|
929
|
+
{
|
|
930
|
+
id: "arrowAlpha",
|
|
931
|
+
type: "range",
|
|
932
|
+
max: 1,
|
|
933
|
+
min: 0,
|
|
934
|
+
step: 0.1,
|
|
935
|
+
label: "Прозрачность стрелки",
|
|
936
|
+
initialValue: LINK_OPTIONS.arrowAlpha,
|
|
937
|
+
},
|
|
938
|
+
{
|
|
939
|
+
id: "arrowSize",
|
|
940
|
+
type: "range",
|
|
941
|
+
max: 10,
|
|
942
|
+
min: 0.1,
|
|
943
|
+
step: 0.1,
|
|
944
|
+
label: "Размер стрелки",
|
|
945
|
+
initialValue: LINK_OPTIONS.arrowSize,
|
|
946
|
+
},
|
|
947
|
+
{
|
|
948
|
+
id: "particleAlpha",
|
|
949
|
+
type: "range",
|
|
950
|
+
max: 1,
|
|
951
|
+
min: 0,
|
|
952
|
+
step: 0.1,
|
|
953
|
+
label: "Прозрачность частиц",
|
|
954
|
+
initialValue: LINK_OPTIONS.particleAlpha,
|
|
955
|
+
},
|
|
956
|
+
{
|
|
957
|
+
id: "particleRadius",
|
|
958
|
+
type: "range",
|
|
959
|
+
max: 10,
|
|
960
|
+
min: 0.1,
|
|
961
|
+
step: 0.1,
|
|
962
|
+
label: "Радиус частиц",
|
|
963
|
+
initialValue: LINK_OPTIONS.particleRadius,
|
|
964
|
+
},
|
|
965
|
+
{
|
|
966
|
+
id: "particleCount",
|
|
967
|
+
type: "range",
|
|
968
|
+
max: 20,
|
|
969
|
+
min: 1,
|
|
970
|
+
step: 1,
|
|
971
|
+
label: "Количество частиц",
|
|
972
|
+
initialValue: LINK_OPTIONS.particleCount,
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
id: "particleSteps",
|
|
976
|
+
type: "range",
|
|
977
|
+
max: 200,
|
|
978
|
+
min: 1,
|
|
979
|
+
step: 1,
|
|
980
|
+
label: "Количество кадров у частиц",
|
|
981
|
+
initialValue: LINK_OPTIONS.particleSteps,
|
|
982
|
+
},
|
|
983
|
+
{
|
|
984
|
+
id: "color",
|
|
985
|
+
type: "color",
|
|
986
|
+
initialValue: "#000000FF",
|
|
987
|
+
label: "Цвет",
|
|
988
|
+
},
|
|
989
|
+
{
|
|
990
|
+
id: "arrowColor",
|
|
991
|
+
type: "color",
|
|
992
|
+
initialValue: "#000000FF",
|
|
993
|
+
label: "Цвет стрелки",
|
|
994
|
+
},
|
|
995
|
+
{
|
|
996
|
+
id: "particleColor",
|
|
997
|
+
type: "color",
|
|
998
|
+
initialValue: "#000000FF",
|
|
999
|
+
label: "Цвет частиц",
|
|
1000
|
+
},
|
|
1001
|
+
{
|
|
1002
|
+
id: "highlightFading",
|
|
1003
|
+
type: "checkbox",
|
|
1004
|
+
label: "Анимация Затухания",
|
|
1005
|
+
initialValue: LINK_OPTIONS.highlightFading,
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
id: "pretty",
|
|
1009
|
+
type: "checkbox",
|
|
1010
|
+
label: "Обсчет соединения",
|
|
1011
|
+
initialValue: LINK_OPTIONS.pretty,
|
|
1012
|
+
},
|
|
1013
|
+
{
|
|
1014
|
+
id: "arrow",
|
|
1015
|
+
type: "checkbox",
|
|
1016
|
+
label: "Стрелка",
|
|
1017
|
+
initialValue: LINK_OPTIONS.arrow,
|
|
1018
|
+
},
|
|
1019
|
+
{
|
|
1020
|
+
id: "arrowHighlightFading",
|
|
1021
|
+
type: "checkbox",
|
|
1022
|
+
label: "Анимация затухания стрелки",
|
|
1023
|
+
initialValue: LINK_OPTIONS.arrowHighlightFading,
|
|
1024
|
+
},
|
|
1025
|
+
{
|
|
1026
|
+
id: "arrowReverseAppear",
|
|
1027
|
+
type: "checkbox",
|
|
1028
|
+
label: "Появление стрелки при анимации",
|
|
1029
|
+
initialValue: LINK_OPTIONS.arrowReverseAppear,
|
|
1030
|
+
},
|
|
1031
|
+
];
|
|
1032
|
+
return keys ? LINK_CONTROLS.filter((control) => keys.includes(control.id)) : LINK_CONTROLS;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
let countTime = 0;
|
|
1036
|
+
let countOperation = 0;
|
|
1037
|
+
function setDrawTime(cb, showEveryTick) {
|
|
1038
|
+
return () => {
|
|
1039
|
+
const start = performance.now();
|
|
1040
|
+
cb();
|
|
1041
|
+
const end = performance.now();
|
|
1042
|
+
const result = end - start;
|
|
1043
|
+
countTime += result;
|
|
1044
|
+
countOperation++;
|
|
1045
|
+
if (showEveryTick) {
|
|
1046
|
+
const average = countTime / countOperation;
|
|
1047
|
+
// eslint-disable-next-line no-console
|
|
1048
|
+
console.log("average draw: ", average, "current draw: ", result);
|
|
1049
|
+
}
|
|
1050
|
+
};
|
|
1051
|
+
}
|
|
1052
|
+
function getDrawTime() {
|
|
1053
|
+
const average = countTime / countOperation;
|
|
1054
|
+
// eslint-disable-next-line no-console
|
|
1055
|
+
console.log("average draw: ", average);
|
|
1056
|
+
}
|
|
1057
|
+
|
|
431
1058
|
class GraphCanvas {
|
|
432
1059
|
/** initial data */
|
|
433
1060
|
nodes;
|
|
434
1061
|
links;
|
|
1062
|
+
particles = {};
|
|
435
1063
|
width;
|
|
436
1064
|
height;
|
|
437
1065
|
root;
|
|
@@ -451,6 +1079,8 @@ class GraphCanvas {
|
|
|
451
1079
|
draw;
|
|
452
1080
|
eventAbortController;
|
|
453
1081
|
cachedNodeText = {};
|
|
1082
|
+
linkOptionsCache = {};
|
|
1083
|
+
nodeOptionsCache = {};
|
|
454
1084
|
isDragging = false;
|
|
455
1085
|
highlightedNode = null;
|
|
456
1086
|
highlightedNeighbors = null;
|
|
@@ -523,20 +1153,35 @@ class GraphCanvas {
|
|
|
523
1153
|
this.updateData(alpha);
|
|
524
1154
|
}
|
|
525
1155
|
changeSettings(options) {
|
|
526
|
-
if (options.graphSettings)
|
|
1156
|
+
if (options.graphSettings) {
|
|
527
1157
|
this.graphSettings = graphSettingsGetter(options.graphSettings, this.graphSettings);
|
|
528
|
-
|
|
1158
|
+
this.draw = this.initDraw();
|
|
1159
|
+
this.initZoom(this.areaTransform);
|
|
1160
|
+
}
|
|
1161
|
+
if (options.forceSettings) {
|
|
529
1162
|
this.forceSettings = forceSettingsGetter(options.forceSettings, this.forceSettings);
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
this.
|
|
534
|
-
|
|
1163
|
+
}
|
|
1164
|
+
if (options.linkSettings) {
|
|
1165
|
+
this.linkSettings = linkSettingsGetter(options.linkSettings, this.linkSettings);
|
|
1166
|
+
this.linkOptionsCache = {};
|
|
1167
|
+
}
|
|
1168
|
+
if (options.nodeSettings) {
|
|
1169
|
+
this.nodeSettings = nodeSettingsGetter(options.nodeSettings, this.nodeSettings);
|
|
1170
|
+
this.cachedNodeText = {};
|
|
1171
|
+
this.nodeOptionsCache = {};
|
|
1172
|
+
}
|
|
1173
|
+
if (options.forceSettings) {
|
|
535
1174
|
return void this.updateSimulation();
|
|
1175
|
+
}
|
|
536
1176
|
this.tick();
|
|
537
1177
|
}
|
|
1178
|
+
clearCache() {
|
|
1179
|
+
this.nodeOptionsCache = {};
|
|
1180
|
+
this.linkOptionsCache = {};
|
|
1181
|
+
this.cachedNodeText = {};
|
|
1182
|
+
}
|
|
538
1183
|
tick() {
|
|
539
|
-
if (!this.simulationWorking)
|
|
1184
|
+
if (!this.simulationWorking && !this.highlightWorking)
|
|
540
1185
|
this.draw();
|
|
541
1186
|
}
|
|
542
1187
|
restart(alpha) {
|
|
@@ -592,6 +1237,8 @@ class GraphCanvas {
|
|
|
592
1237
|
}
|
|
593
1238
|
clearDataDependencies() {
|
|
594
1239
|
this.cachedNodeText = {};
|
|
1240
|
+
this.nodeOptionsCache = {};
|
|
1241
|
+
this.linkOptionsCache = {};
|
|
595
1242
|
}
|
|
596
1243
|
updateData(alpha) {
|
|
597
1244
|
this.clearDataDependencies();
|
|
@@ -615,7 +1262,7 @@ class GraphCanvas {
|
|
|
615
1262
|
this.initZoom();
|
|
616
1263
|
this.initResize();
|
|
617
1264
|
this.initPointer();
|
|
618
|
-
if (!this.simulationWorking)
|
|
1265
|
+
if (!this.simulationWorking && !this.highlightWorking)
|
|
619
1266
|
this.draw();
|
|
620
1267
|
}
|
|
621
1268
|
init() {
|
|
@@ -636,6 +1283,8 @@ class GraphCanvas {
|
|
|
636
1283
|
})
|
|
637
1284
|
.on("end", () => {
|
|
638
1285
|
this.listeners.onSimulationEnd?.(this.state);
|
|
1286
|
+
if (this.graphSettings.showDrawTime)
|
|
1287
|
+
getDrawTime();
|
|
639
1288
|
});
|
|
640
1289
|
this.initSimulationForces();
|
|
641
1290
|
}
|
|
@@ -658,9 +1307,9 @@ class GraphCanvas {
|
|
|
658
1307
|
.distanceMax(this.forceSettings.chargeDistanceMax)
|
|
659
1308
|
.distanceMin(this.forceSettings.chargeDistanceMin))
|
|
660
1309
|
.force("center", d3Force.forceCenter(this.forceSettings.centerPosition.x ?? 0, this.forceSettings.centerPosition.y ?? 0).strength(this.forceSettings.centerStrength));
|
|
661
|
-
this.initCollideForce();
|
|
1310
|
+
this.initCollideForce(true);
|
|
662
1311
|
}
|
|
663
|
-
initCollideForce() {
|
|
1312
|
+
initCollideForce(forceUpdate) {
|
|
664
1313
|
if (!this.simulation)
|
|
665
1314
|
return;
|
|
666
1315
|
if (!this.forceSettings.collideOn) {
|
|
@@ -671,9 +1320,10 @@ class GraphCanvas {
|
|
|
671
1320
|
const isHasMax = this.forceSettings.collideOffMax.links != 0 && this.forceSettings.collideOffMax.nodes != 0;
|
|
672
1321
|
const isMaxCollideNodes = isHasMax && this.forceSettings.collideOffMax.nodes < this.nodes.length;
|
|
673
1322
|
const isMaxCollideLinks = isHasMax && this.forceSettings.collideOffMax.links < this.links.length;
|
|
674
|
-
if (isMaxCollideNodes && isMaxCollideLinks)
|
|
1323
|
+
if (isMaxCollideNodes && isMaxCollideLinks) {
|
|
675
1324
|
this.simulation.force("collide", null);
|
|
676
|
-
|
|
1325
|
+
}
|
|
1326
|
+
else if (!this.simulation.force("collide") || forceUpdate) {
|
|
677
1327
|
this.simulation.force("collide", d3Force.forceCollide()
|
|
678
1328
|
.radius((node, index) => {
|
|
679
1329
|
if (this.forceSettings.collideRadius) {
|
|
@@ -691,6 +1341,7 @@ class GraphCanvas {
|
|
|
691
1341
|
})
|
|
692
1342
|
.strength(this.forceSettings.collideStrength)
|
|
693
1343
|
.iterations(this.forceSettings.collideIterations));
|
|
1344
|
+
}
|
|
694
1345
|
}
|
|
695
1346
|
initArea() {
|
|
696
1347
|
if (!this.area || !this.context || !this.container) {
|
|
@@ -725,19 +1376,27 @@ class GraphCanvas {
|
|
|
725
1376
|
this.highlightProgress -= this.graphSettings.highlightDownStep;
|
|
726
1377
|
if (!this.simulationWorking)
|
|
727
1378
|
return void requestAnimationFrame(() => this.draw());
|
|
728
|
-
|
|
1379
|
+
if (!this.linkSettings.particles)
|
|
1380
|
+
return;
|
|
729
1381
|
}
|
|
730
1382
|
if (this.highlightWorking && this.highlightProgress < 1) {
|
|
731
1383
|
this.highlightProgress += this.graphSettings.highlightUpStep;
|
|
732
1384
|
if (!this.simulationWorking)
|
|
733
1385
|
return void requestAnimationFrame(() => this.draw());
|
|
734
|
-
|
|
1386
|
+
if (!this.linkSettings.particles)
|
|
1387
|
+
return;
|
|
1388
|
+
}
|
|
1389
|
+
if (this.linkSettings.particles && this.highlightWorking && !this.simulationWorking) {
|
|
1390
|
+
return void requestAnimationFrame(() => this.draw());
|
|
735
1391
|
}
|
|
736
1392
|
if (!this.highlightWorking && this.highlightProgress <= 0) {
|
|
737
|
-
if (this.highlightedNeighbors)
|
|
1393
|
+
if (this.highlightedNeighbors || this.highlightedNode) {
|
|
738
1394
|
this.highlightedNeighbors = null;
|
|
739
|
-
if (this.highlightedNode)
|
|
740
1395
|
this.highlightedNode = null;
|
|
1396
|
+
this.particles = {};
|
|
1397
|
+
if (!this.simulationWorking)
|
|
1398
|
+
return void requestAnimationFrame(() => this.draw());
|
|
1399
|
+
}
|
|
741
1400
|
}
|
|
742
1401
|
this.highlightDrawing = false;
|
|
743
1402
|
}
|
|
@@ -760,13 +1419,13 @@ class GraphCanvas {
|
|
|
760
1419
|
this.context.clearRect(0, 0, this.width, this.height);
|
|
761
1420
|
this.context.translate(this.areaTransform.x, this.areaTransform.y);
|
|
762
1421
|
this.context.scale(this.areaTransform.k, this.areaTransform.k);
|
|
1422
|
+
const textRenders = [];
|
|
1423
|
+
const nodeRenders = [];
|
|
1424
|
+
this.nodes.forEach(getDrawNode(nodeRenders, textRenders, state).bind(this));
|
|
763
1425
|
/** links */
|
|
764
|
-
this.context.beginPath();
|
|
765
1426
|
this.links.forEach(getDrawLink(state).bind(this));
|
|
766
|
-
this.context.stroke();
|
|
767
1427
|
/** nodes */
|
|
768
|
-
|
|
769
|
-
this.nodes.forEach(getDrawNode(textRenders, state).bind(this));
|
|
1428
|
+
nodeRenders.forEach((render) => render());
|
|
770
1429
|
textRenders.forEach((render) => render());
|
|
771
1430
|
this.context.restore();
|
|
772
1431
|
this.listeners.onDrawFinished?.(state);
|
|
@@ -782,54 +1441,155 @@ class GraphCanvas {
|
|
|
782
1441
|
!link.target.x ||
|
|
783
1442
|
!link.target.y)
|
|
784
1443
|
return;
|
|
785
|
-
|
|
1444
|
+
if (!link.source._visible && !link.target._visible)
|
|
1445
|
+
return;
|
|
1446
|
+
const id = `${link.target.id}${link.source.id}`;
|
|
1447
|
+
let linkOptions;
|
|
1448
|
+
if (this.linkSettings.cache && this.linkOptionsCache[id]) {
|
|
1449
|
+
linkOptions = this.linkOptionsCache[id];
|
|
1450
|
+
}
|
|
1451
|
+
else {
|
|
1452
|
+
linkOptions = linkIterationExtractor(link, index, this.links, state, this.linkSettings.options ?? {}, linkOptionsGetter);
|
|
1453
|
+
if (this.linkSettings.cache) {
|
|
1454
|
+
this.linkOptionsCache[id] = linkOptions;
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
786
1457
|
if (linkOptions.drawLink) {
|
|
787
1458
|
linkOptions.drawLink(link, linkOptions, state);
|
|
788
1459
|
return;
|
|
789
1460
|
}
|
|
790
1461
|
let alpha = linkOptions.alpha;
|
|
1462
|
+
let arrowAlpha = linkOptions.arrowReverseAppear ? 0 : linkOptions.arrowAlpha;
|
|
791
1463
|
if (this.highlightedNeighbors && this.highlightedNode) {
|
|
792
1464
|
/** Not highlighted */
|
|
793
1465
|
if (this.highlightedNode.id != link.source.id &&
|
|
794
1466
|
this.highlightedNode.id != link.target.id) {
|
|
795
|
-
if (linkOptions.highlightFading)
|
|
796
|
-
|
|
797
|
-
this.graphSettings.highlightLinkFadingMin
|
|
798
|
-
|
|
1467
|
+
if (linkOptions.highlightFading) {
|
|
1468
|
+
const min = this.graphSettings.highlightLinkFadingMin < alpha
|
|
1469
|
+
? this.graphSettings.highlightLinkFadingMin
|
|
1470
|
+
: alpha;
|
|
1471
|
+
alpha = animationByProgress(min, alpha - min, 1 - this.highlightProgress);
|
|
1472
|
+
}
|
|
1473
|
+
if (linkOptions.arrow &&
|
|
1474
|
+
linkOptions.arrowHighlightFading &&
|
|
1475
|
+
!linkOptions.arrowReverseAppear) {
|
|
1476
|
+
const min = this.graphSettings.highlightArrowFadingMin < arrowAlpha
|
|
1477
|
+
? this.graphSettings.highlightArrowFadingMin
|
|
1478
|
+
: arrowAlpha;
|
|
1479
|
+
arrowAlpha = animationByProgress(min, arrowAlpha - min, 1 - this.highlightProgress);
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
else {
|
|
1483
|
+
// eslint-disable-next-line no-lonely-if
|
|
1484
|
+
if (linkOptions.arrow && linkOptions.arrowReverseAppear) {
|
|
1485
|
+
/** Highlighted */
|
|
1486
|
+
arrowAlpha = animationByProgress(0, linkOptions.arrowAlpha, this.highlightProgress);
|
|
1487
|
+
}
|
|
799
1488
|
}
|
|
800
|
-
this.context.beginPath();
|
|
801
1489
|
}
|
|
1490
|
+
/** Link */
|
|
1491
|
+
this.context.beginPath();
|
|
802
1492
|
this.context.globalAlpha = alpha;
|
|
803
1493
|
this.context.strokeStyle = linkOptions.color;
|
|
804
1494
|
this.context.lineWidth = linkOptions.width;
|
|
1495
|
+
let xStart = link.source.x;
|
|
1496
|
+
let yStart = link.source.y;
|
|
1497
|
+
let xEnd = link.target.x;
|
|
1498
|
+
let yEnd = link.target.y;
|
|
805
1499
|
if (linkOptions.pretty) {
|
|
806
|
-
const
|
|
1500
|
+
const isHasArrow = linkOptions.arrow && arrowAlpha > 0;
|
|
1501
|
+
const { x1, x2, y1, y2 } = calculateLinkPositionByRadius(link, isHasArrow ? linkOptions.arrowSize : 0) ?? {
|
|
807
1502
|
x1: 0,
|
|
808
1503
|
x2: 0,
|
|
809
1504
|
y1: 0,
|
|
810
1505
|
y2: 0,
|
|
811
1506
|
};
|
|
812
|
-
|
|
813
|
-
|
|
1507
|
+
xStart = x1;
|
|
1508
|
+
xEnd = x2;
|
|
1509
|
+
yStart = y1;
|
|
1510
|
+
yEnd = y2;
|
|
814
1511
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
1512
|
+
this.context.moveTo(xStart, yStart);
|
|
1513
|
+
this.context.lineTo(xEnd, yEnd);
|
|
1514
|
+
this.context.stroke();
|
|
1515
|
+
/** Particle */
|
|
1516
|
+
if (this.linkSettings.particles &&
|
|
1517
|
+
this.highlightedNode &&
|
|
1518
|
+
(this.highlightedNode.id === link.source.id || this.highlightedNode.id === link.target.id)) {
|
|
1519
|
+
if (!this.particles[id]) {
|
|
1520
|
+
const sourceId = link.source.id;
|
|
1521
|
+
const targetId = link.target.id;
|
|
1522
|
+
this.particles[id] = Array.from({ length: linkOptions.particleCount }, (_, index) => {
|
|
1523
|
+
return {
|
|
1524
|
+
step: 0,
|
|
1525
|
+
wait: index * (linkOptions.particleSteps / linkOptions.particleCount),
|
|
1526
|
+
sourceId,
|
|
1527
|
+
targetId,
|
|
1528
|
+
};
|
|
1529
|
+
});
|
|
1530
|
+
}
|
|
1531
|
+
this.particles[id].forEach((particle) => {
|
|
1532
|
+
if (!this.context)
|
|
1533
|
+
return;
|
|
1534
|
+
getParticlePosition({
|
|
1535
|
+
particle,
|
|
1536
|
+
totalSteps: linkOptions.particleSteps,
|
|
1537
|
+
xEnd,
|
|
1538
|
+
xStart,
|
|
1539
|
+
yEnd,
|
|
1540
|
+
yStart,
|
|
1541
|
+
});
|
|
1542
|
+
if (particle.x != undefined && particle.y != undefined) {
|
|
1543
|
+
this.context.beginPath();
|
|
1544
|
+
this.context.arc(particle.x, particle.y, linkOptions.particleRadius, 0, Math.PI * 2);
|
|
1545
|
+
this.context.fillStyle = linkOptions.particleColor;
|
|
1546
|
+
this.context.fill();
|
|
1547
|
+
this.context.stroke();
|
|
1548
|
+
}
|
|
1549
|
+
});
|
|
818
1550
|
}
|
|
819
|
-
|
|
1551
|
+
/** Arrow */
|
|
1552
|
+
if (linkOptions.arrow && arrowAlpha > 0) {
|
|
1553
|
+
const { x1: xStart, x2: xEnd, y1: yStart, y2: yEnd, } = calculateLinkPositionByRadius(link) ?? {
|
|
1554
|
+
x1: 0,
|
|
1555
|
+
x2: 0,
|
|
1556
|
+
y1: 0,
|
|
1557
|
+
y2: 0,
|
|
1558
|
+
};
|
|
1559
|
+
const angle = Math.atan2(yEnd - yStart, xEnd - xStart);
|
|
1560
|
+
this.context.beginPath();
|
|
1561
|
+
this.context.globalAlpha = arrowAlpha;
|
|
1562
|
+
this.context.moveTo(xEnd, yEnd);
|
|
1563
|
+
this.context.lineTo(xEnd - linkOptions.arrowSize * Math.cos(angle - Math.PI / 6), yEnd - linkOptions.arrowSize * Math.sin(angle - Math.PI / 6));
|
|
1564
|
+
this.context.lineTo(xEnd - linkOptions.arrowSize * Math.cos(angle + Math.PI / 6), yEnd - linkOptions.arrowSize * Math.sin(angle + Math.PI / 6));
|
|
1565
|
+
this.context.closePath();
|
|
1566
|
+
this.context.fillStyle = linkOptions.arrowColor;
|
|
1567
|
+
this.context.fill();
|
|
820
1568
|
this.context.stroke();
|
|
1569
|
+
}
|
|
821
1570
|
if (linkOptions.drawExtraLink) {
|
|
822
1571
|
linkOptions.drawExtraLink(link, { ...linkOptions, alpha }, state);
|
|
823
1572
|
}
|
|
824
1573
|
};
|
|
825
1574
|
}
|
|
826
|
-
function getDrawNode(textRenders, state) {
|
|
1575
|
+
function getDrawNode(nodeRenders, textRenders, state) {
|
|
827
1576
|
return function drawNode(node, index) {
|
|
828
1577
|
if (!this.context || !node.x || !node.y)
|
|
829
1578
|
return;
|
|
830
|
-
|
|
1579
|
+
let nodeOptions;
|
|
1580
|
+
if (this.nodeSettings.cache && this.nodeOptionsCache[node.id]) {
|
|
1581
|
+
nodeOptions = this.nodeOptionsCache[node.id];
|
|
1582
|
+
}
|
|
1583
|
+
else {
|
|
1584
|
+
nodeOptions = nodeIterationExtractor(node, index, this.nodes, state, this.nodeSettings.options ?? {}, nodeOptionsGetter);
|
|
1585
|
+
if (this.nodeSettings.cache) {
|
|
1586
|
+
this.nodeOptionsCache[node.id] = nodeOptions;
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
831
1589
|
if (nodeOptions.nodeDraw) {
|
|
832
|
-
|
|
1590
|
+
nodeRenders.push(() => {
|
|
1591
|
+
nodeOptions?.nodeDraw?.(node, nodeOptions, state);
|
|
1592
|
+
});
|
|
833
1593
|
return;
|
|
834
1594
|
}
|
|
835
1595
|
let alpha = nodeOptions.alpha;
|
|
@@ -845,15 +1605,16 @@ class GraphCanvas {
|
|
|
845
1605
|
/** Not highlighted */
|
|
846
1606
|
if (!this.highlightedNeighbors.has(node.id) && this.highlightedNode.id != node.id) {
|
|
847
1607
|
if (nodeOptions.highlightFading) {
|
|
848
|
-
|
|
849
|
-
this.graphSettings.highlightFadingMin
|
|
850
|
-
|
|
1608
|
+
const min = this.graphSettings.highlightFadingMin < alpha
|
|
1609
|
+
? this.graphSettings.highlightFadingMin
|
|
1610
|
+
: alpha;
|
|
1611
|
+
alpha = animationByProgress(min, alpha - min, 1 - this.highlightProgress);
|
|
851
1612
|
}
|
|
852
1613
|
if (nodeOptions.highlightTextFading) {
|
|
853
|
-
|
|
854
|
-
this.graphSettings.highlightTextFadingMin
|
|
855
|
-
|
|
856
|
-
|
|
1614
|
+
const min = this.graphSettings.highlightTextFadingMin < textAlpha
|
|
1615
|
+
? this.graphSettings.highlightTextFadingMin
|
|
1616
|
+
: textAlpha;
|
|
1617
|
+
textAlpha = animationByProgress(min, textAlpha - min, 1 - this.highlightProgress);
|
|
857
1618
|
}
|
|
858
1619
|
if (nodeOptions.highlightColor) {
|
|
859
1620
|
const colorRgb = extractRgb(colorToRgb(color));
|
|
@@ -868,20 +1629,14 @@ class GraphCanvas {
|
|
|
868
1629
|
(this.graphSettings.highlightOnlyRoot && this.highlightedNode.id === node.id)) {
|
|
869
1630
|
/** Highlighted */
|
|
870
1631
|
if (nodeOptions.highlightSizing) {
|
|
871
|
-
|
|
872
|
-
radiusInitial += ((radiusMax - radiusInitial) / 100) * (this.highlightProgress * 100);
|
|
1632
|
+
radiusInitial = animationByProgress(radiusInitial, this.graphSettings.highlightSizingAdditional, this.highlightProgress);
|
|
873
1633
|
}
|
|
874
1634
|
if (nodeOptions.highlightTextSizing) {
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
textSize += ((textSizeMax - textSize) / 100) * (this.highlightProgress * 100);
|
|
881
|
-
textShiftX += ((textShiftXMax - textShiftX) / 100) * (this.highlightProgress * 100);
|
|
882
|
-
textShiftY += ((textShiftYMax - textShiftY) / 100) * (this.highlightProgress * 100);
|
|
883
|
-
textWeight += ((textWeightMax - textWeight) / 100) * (this.highlightProgress * 100);
|
|
884
|
-
textWidth += ((textWidthMax - textWidth) / 100) * (this.highlightProgress * 100);
|
|
1635
|
+
textSize = animationByProgress(textSize, this.graphSettings.highlightTextSizingAdditional, this.highlightProgress);
|
|
1636
|
+
textShiftX = animationByProgress(textShiftX, this.graphSettings.highlightTextShiftXAdditional, this.highlightProgress);
|
|
1637
|
+
textShiftY = animationByProgress(textShiftY, this.graphSettings.highlightTextShiftYAdditional, this.highlightProgress);
|
|
1638
|
+
textWeight = animationByProgress(textWeight, this.graphSettings.highlightTextWeightAdditional, this.highlightProgress);
|
|
1639
|
+
textWidth = animationByProgress(textWidth, this.graphSettings.highlightTextWidthAdditional, this.highlightProgress);
|
|
885
1640
|
}
|
|
886
1641
|
}
|
|
887
1642
|
}
|
|
@@ -893,8 +1648,31 @@ class GraphCanvas {
|
|
|
893
1648
|
linkCount: node.linkCount,
|
|
894
1649
|
});
|
|
895
1650
|
node._radius = radius;
|
|
896
|
-
|
|
897
|
-
|
|
1651
|
+
if (!isNodeVisible({
|
|
1652
|
+
height: this.height,
|
|
1653
|
+
width: this.width,
|
|
1654
|
+
x: node.x,
|
|
1655
|
+
y: node.y,
|
|
1656
|
+
radius,
|
|
1657
|
+
transform: this.areaTransform,
|
|
1658
|
+
})) {
|
|
1659
|
+
node._visible = false;
|
|
1660
|
+
return;
|
|
1661
|
+
}
|
|
1662
|
+
node._visible = true;
|
|
1663
|
+
nodeRenders.push(() => {
|
|
1664
|
+
if (!this.context || !node.x || !node.y)
|
|
1665
|
+
return;
|
|
1666
|
+
this.context.beginPath();
|
|
1667
|
+
this.context.globalAlpha = alpha;
|
|
1668
|
+
/** circle */
|
|
1669
|
+
this.context.lineWidth = nodeOptions.borderWidth;
|
|
1670
|
+
this.context.strokeStyle = nodeOptions.borderColor;
|
|
1671
|
+
this.context.fillStyle = color;
|
|
1672
|
+
this.context.arc(node.x, node.y, radius, 0, 2 * Math.PI);
|
|
1673
|
+
this.context.fill();
|
|
1674
|
+
this.context.stroke();
|
|
1675
|
+
});
|
|
898
1676
|
/** text */
|
|
899
1677
|
if (nodeOptions.textVisible && nodeOptions.text) {
|
|
900
1678
|
textRenders.push(() => {
|
|
@@ -949,29 +1727,27 @@ class GraphCanvas {
|
|
|
949
1727
|
}
|
|
950
1728
|
});
|
|
951
1729
|
}
|
|
952
|
-
/** circle */
|
|
953
|
-
this.context.lineWidth = nodeOptions.borderWidth;
|
|
954
|
-
this.context.strokeStyle = nodeOptions.borderColor;
|
|
955
|
-
this.context.fillStyle = color;
|
|
956
|
-
this.context.arc(node.x, node.y, radius, 0, 2 * Math.PI);
|
|
957
|
-
this.context.fill();
|
|
958
|
-
this.context.stroke();
|
|
959
1730
|
if (nodeOptions.nodeExtraDraw) {
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1731
|
+
nodeRenders.push(() => {
|
|
1732
|
+
nodeOptions?.nodeExtraDraw?.(node, {
|
|
1733
|
+
...nodeOptions,
|
|
1734
|
+
radius,
|
|
1735
|
+
alpha,
|
|
1736
|
+
color,
|
|
1737
|
+
textAlpha,
|
|
1738
|
+
textSize,
|
|
1739
|
+
textShiftX,
|
|
1740
|
+
textShiftY,
|
|
1741
|
+
textWeight,
|
|
1742
|
+
textWidth,
|
|
1743
|
+
}, state);
|
|
1744
|
+
});
|
|
972
1745
|
}
|
|
973
1746
|
};
|
|
974
1747
|
}
|
|
1748
|
+
if (this.graphSettings.showDrawTime) {
|
|
1749
|
+
return setDrawTime(draw.bind(this), this.graphSettings.showDrawTimeEveryTick);
|
|
1750
|
+
}
|
|
975
1751
|
return draw;
|
|
976
1752
|
}
|
|
977
1753
|
initResize() {
|
|
@@ -1165,7 +1941,7 @@ class GraphCanvas {
|
|
|
1165
1941
|
this.listeners.onEndDragFinished?.(event, this.state);
|
|
1166
1942
|
}));
|
|
1167
1943
|
}
|
|
1168
|
-
initZoom() {
|
|
1944
|
+
initZoom(currentZoom) {
|
|
1169
1945
|
if (!this.area)
|
|
1170
1946
|
throw new Error("bad init data");
|
|
1171
1947
|
const zoomInstance = d3Zoom.zoom()
|
|
@@ -1173,7 +1949,9 @@ class GraphCanvas {
|
|
|
1173
1949
|
.on("zoom", (event) => {
|
|
1174
1950
|
this.listeners.onZoom?.(event);
|
|
1175
1951
|
this.areaTransform = event.transform;
|
|
1176
|
-
|
|
1952
|
+
this.linkOptionsCache = {};
|
|
1953
|
+
this.nodeOptionsCache = {};
|
|
1954
|
+
if (!this.simulationWorking && !this.highlightWorking)
|
|
1177
1955
|
requestAnimationFrame(() => this.draw());
|
|
1178
1956
|
});
|
|
1179
1957
|
if (this.graphSettings.translateExtentEnable) {
|
|
@@ -1188,18 +1966,24 @@ class GraphCanvas {
|
|
|
1188
1966
|
]);
|
|
1189
1967
|
}
|
|
1190
1968
|
d3Selection.select(this.area).call(zoomInstance).on("dblclick.zoom", null);
|
|
1191
|
-
const zoomInitial = this.graphSettings.zoomInitial;
|
|
1969
|
+
const zoomInitial = currentZoom ?? this.graphSettings.zoomInitial;
|
|
1192
1970
|
this.areaTransform = new d3Zoom.ZoomTransform(zoomInitial?.k ?? 1, zoomInitial?.x ?? this.width / 2, zoomInitial?.y ?? this.height / 2);
|
|
1193
1971
|
d3Zoom.zoom().transform(d3Selection.select(this.area), this.areaTransform);
|
|
1194
1972
|
}
|
|
1195
1973
|
}
|
|
1196
1974
|
|
|
1197
1975
|
exports.GraphCanvas = GraphCanvas;
|
|
1976
|
+
exports.animationByProgress = animationByProgress;
|
|
1198
1977
|
exports.calculateLinkPositionByRadius = calculateLinkPositionByRadius;
|
|
1199
1978
|
exports.colorToRgb = colorToRgb;
|
|
1200
1979
|
exports.drawText = drawText;
|
|
1201
1980
|
exports.extractRgb = extractRgb;
|
|
1202
1981
|
exports.fadeRgb = fadeRgb;
|
|
1982
|
+
exports.getForceControls = getForceControls;
|
|
1983
|
+
exports.getGraphControls = getGraphControls;
|
|
1984
|
+
exports.getLinkControls = getLinkControls;
|
|
1985
|
+
exports.getNodeControls = getNodeControls;
|
|
1986
|
+
exports.getParticlePosition = getParticlePosition;
|
|
1203
1987
|
exports.linkIterationExtractor = linkIterationExtractor;
|
|
1204
1988
|
exports.linkOptionsGetter = linkOptionsGetter;
|
|
1205
1989
|
exports.nodeIterationExtractor = nodeIterationExtractor;
|