@krainovsd/graph 0.12.0-beta.2 → 0.12.0-beta.4
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 +351 -247
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/esm/constants/link-controls.js +0 -6
- package/lib/esm/constants/link-controls.js.map +1 -1
- package/lib/esm/constants/node-controls.js +71 -24
- package/lib/esm/constants/node-controls.js.map +1 -1
- package/lib/esm/lib/draw-time.js +2 -2
- package/lib/esm/lib/draw-time.js.map +1 -1
- package/lib/esm/module/GraphCanvas/GraphCanvas.js +29 -25
- package/lib/esm/module/GraphCanvas/GraphCanvas.js.map +1 -1
- package/lib/esm/module/GraphCanvas/constants/link-settings.js +0 -1
- package/lib/esm/module/GraphCanvas/constants/link-settings.js.map +1 -1
- package/lib/esm/module/GraphCanvas/constants/node-settings.js +10 -5
- package/lib/esm/module/GraphCanvas/constants/node-settings.js.map +1 -1
- package/lib/esm/module/GraphCanvas/lib/settings/node-settings-getter.js +20 -4
- package/lib/esm/module/GraphCanvas/lib/settings/node-settings-getter.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/draw-links.js +7 -20
- package/lib/esm/module/GraphCanvas/slices/draw-links.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/draw-nodes.js +25 -117
- package/lib/esm/module/GraphCanvas/slices/draw-nodes.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/draw-text.js +1 -24
- package/lib/esm/module/GraphCanvas/slices/draw-text.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/init-draw.js +25 -11
- package/lib/esm/module/GraphCanvas/slices/init-draw.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/init-pointer.js +3 -3
- package/lib/esm/module/GraphCanvas/slices/init-pointer.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/init-simulation.js +20 -8
- package/lib/esm/module/GraphCanvas/slices/init-simulation.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/init-zoom.js +4 -2
- package/lib/esm/module/GraphCanvas/slices/init-zoom.js.map +1 -1
- package/lib/esm/module/GraphCanvas/slices/update-link-cache.js +19 -0
- package/lib/esm/module/GraphCanvas/slices/update-link-cache.js.map +1 -0
- package/lib/esm/module/GraphCanvas/slices/update-node-cache.js +136 -0
- package/lib/esm/module/GraphCanvas/slices/update-node-cache.js.map +1 -0
- package/lib/index.d.ts +32 -33
- package/package.json +8 -4
package/lib/cjs/index.cjs
CHANGED
|
@@ -113,7 +113,6 @@ const HIGHLIGHT_SETTINGS = {
|
|
|
113
113
|
};
|
|
114
114
|
|
|
115
115
|
const LINK_SETTINGS = {
|
|
116
|
-
cacheOptions: true,
|
|
117
116
|
prettyDraw: true,
|
|
118
117
|
linkScaleSwitch: 1,
|
|
119
118
|
linkColorAfterScaleSwitch: "#000000FF",
|
|
@@ -142,13 +141,18 @@ const LINK_OPTIONS = {
|
|
|
142
141
|
};
|
|
143
142
|
|
|
144
143
|
const NODE_SETTINGS = {
|
|
145
|
-
cacheOptions: true,
|
|
146
144
|
nodeRadiusFlexible: true,
|
|
147
|
-
|
|
148
|
-
|
|
145
|
+
nodeRadiusLinkCountForStep: 5,
|
|
146
|
+
nodeRadiusIncrementByStep: 1,
|
|
147
|
+
nodeRadiusMaxLinearSteps: 5,
|
|
148
|
+
nodeRadiusLinkCountDividerForLog: 25,
|
|
149
|
+
nodeRadiusLogFactor: 2.5,
|
|
149
150
|
nodeSizeFlexible: true,
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
nodeSizeLinkCountForStep: 5,
|
|
152
|
+
nodeSizeIncrementByStep: 0.1,
|
|
153
|
+
nodeSizeMaxLinearSteps: 5,
|
|
154
|
+
nodeSizeLinkCountDividerForLog: 25,
|
|
155
|
+
nodeSizeLogFactor: 2.5,
|
|
152
156
|
textScaleMin: 1.5,
|
|
153
157
|
textScaleMax: 18,
|
|
154
158
|
textSizeMin: 3.5,
|
|
@@ -308,9 +312,9 @@ function rgbAnimationByProgress(start, end, progress) {
|
|
|
308
312
|
let countTime = 0;
|
|
309
313
|
let countOperation = 0;
|
|
310
314
|
function setDrawTime(cb, showEveryTick) {
|
|
311
|
-
return () => {
|
|
315
|
+
return (recursive) => {
|
|
312
316
|
const start = performance.now();
|
|
313
|
-
cb();
|
|
317
|
+
cb(recursive);
|
|
314
318
|
const end = performance.now();
|
|
315
319
|
const result = end - start;
|
|
316
320
|
countTime += result;
|
|
@@ -378,13 +382,29 @@ function nodeTextSizeGetter(transform, nodeSettings) {
|
|
|
378
382
|
}
|
|
379
383
|
return { textSize, textShiftY };
|
|
380
384
|
}
|
|
381
|
-
function nodeRadiusGetter({ radiusFlexible, radiusInitial,
|
|
382
|
-
|
|
385
|
+
function nodeRadiusGetter({ radiusFlexible, linkCount, radiusInitial, radiusIncrementByStep, radiusLinkCountDividerForLog, radiusLinkCountForStep, radiusLogFactor, radiusMaxLinearSteps, }) {
|
|
386
|
+
if (!radiusFlexible || !linkCount)
|
|
387
|
+
return radiusInitial;
|
|
388
|
+
const steps = linkCount / radiusLinkCountForStep;
|
|
389
|
+
if (steps < radiusMaxLinearSteps) {
|
|
390
|
+
return steps * radiusIncrementByStep + radiusInitial;
|
|
391
|
+
}
|
|
392
|
+
return (radiusInitial +
|
|
393
|
+
radiusMaxLinearSteps * radiusIncrementByStep +
|
|
394
|
+
radiusLogFactor * Math.log10(linkCount / radiusLinkCountDividerForLog));
|
|
383
395
|
}
|
|
384
|
-
function nodeSizeGetter({ heightInitial, linkCount,
|
|
396
|
+
function nodeSizeGetter({ heightInitial, linkCount, sizeFlexible, widthInitial, sizeIncrementByStep, sizeLinkCountDividerForLog, sizeLinkCountForStep, sizeLogFactor, sizeMaxLinearSteps, }) {
|
|
385
397
|
let additionalSizeCoefficient = 1;
|
|
386
398
|
if (sizeFlexible && linkCount != undefined) {
|
|
387
|
-
|
|
399
|
+
const steps = linkCount / sizeLinkCountForStep;
|
|
400
|
+
if (steps < sizeMaxLinearSteps) {
|
|
401
|
+
additionalSizeCoefficient += steps * sizeIncrementByStep;
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
additionalSizeCoefficient +=
|
|
405
|
+
sizeMaxLinearSteps * sizeIncrementByStep +
|
|
406
|
+
sizeLogFactor * Math.log10(linkCount / sizeLinkCountDividerForLog);
|
|
407
|
+
}
|
|
388
408
|
}
|
|
389
409
|
return {
|
|
390
410
|
width: widthInitial * additionalSizeCoefficient,
|
|
@@ -1205,7 +1225,7 @@ function initDnd() {
|
|
|
1205
1225
|
}
|
|
1206
1226
|
|
|
1207
1227
|
function getDrawLink() {
|
|
1208
|
-
return function drawLink(link
|
|
1228
|
+
return function drawLink(link) {
|
|
1209
1229
|
if (!this.context ||
|
|
1210
1230
|
typeof link.source !== "object" ||
|
|
1211
1231
|
typeof link.target !== "object" ||
|
|
@@ -1221,16 +1241,9 @@ function getDrawLink() {
|
|
|
1221
1241
|
if (!link.source._visible && !link.target._visible)
|
|
1222
1242
|
return;
|
|
1223
1243
|
const id = `${link.target.id}${link.source.id}`;
|
|
1224
|
-
|
|
1225
|
-
if (
|
|
1226
|
-
|
|
1227
|
-
}
|
|
1228
|
-
else {
|
|
1229
|
-
linkOptions = linkIterationExtractor(link, index, this.links, this, this.linkSettings.options ?? {}, linkOptionsGetter);
|
|
1230
|
-
if (this.linkSettings.cacheOptions) {
|
|
1231
|
-
this.linkOptionsCache[id] = linkOptions;
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1244
|
+
const linkOptions = this.linkOptionsCache[id];
|
|
1245
|
+
if (!linkOptions)
|
|
1246
|
+
return;
|
|
1234
1247
|
if (linkOptions.drawLink) {
|
|
1235
1248
|
linkOptions.drawLink.call(this, link, linkOptions);
|
|
1236
1249
|
return;
|
|
@@ -1327,7 +1340,9 @@ function getDrawLink() {
|
|
|
1327
1340
|
let xEnd = link.target.x;
|
|
1328
1341
|
let yEnd = link.target.y;
|
|
1329
1342
|
let linkDistance = 0;
|
|
1330
|
-
if (this.linkSettings.prettyDraw ||
|
|
1343
|
+
if (this.linkSettings.prettyDraw ||
|
|
1344
|
+
this.linkSettings.particleFlexSpeed ||
|
|
1345
|
+
(this.linkSettings.arrow && arrowAlpha > 0)) {
|
|
1331
1346
|
const isHasArrow = this.linkSettings.arrow && arrowAlpha > 0;
|
|
1332
1347
|
const position = calculateLinkPositionByNode(link, isHasArrow ? arrowSize : 0);
|
|
1333
1348
|
if (position) {
|
|
@@ -1408,12 +1423,6 @@ function getDrawLink() {
|
|
|
1408
1423
|
}
|
|
1409
1424
|
/** Arrow */
|
|
1410
1425
|
if (this.linkSettings.arrow && arrowAlpha > 0) {
|
|
1411
|
-
const { x1: xStart, x2: xEnd, y1: yStart, y2: yEnd, } = calculateLinkPositionByNode(link) ?? {
|
|
1412
|
-
x1: 0,
|
|
1413
|
-
x2: 0,
|
|
1414
|
-
y1: 0,
|
|
1415
|
-
y2: 0,
|
|
1416
|
-
};
|
|
1417
1426
|
this.context.beginPath();
|
|
1418
1427
|
this.context.globalAlpha = arrowAlpha;
|
|
1419
1428
|
this.context.strokeStyle = arrowBorderColor;
|
|
@@ -1436,33 +1445,10 @@ function getDrawLink() {
|
|
|
1436
1445
|
}
|
|
1437
1446
|
|
|
1438
1447
|
const SPACE = " ";
|
|
1439
|
-
function drawText({ context,
|
|
1448
|
+
function drawText({ context, textAlign, textColor, textFont, textStyle, textGap, textWeight, textSize, x, y, lines, }) {
|
|
1440
1449
|
context.font = `${textStyle} normal ${textWeight} ${textSize}px ${textFont}`;
|
|
1441
1450
|
context.fillStyle = textColor;
|
|
1442
1451
|
context.textAlign = textAlign;
|
|
1443
|
-
if (cachedNodeText[id] != undefined) {
|
|
1444
|
-
cachedNodeText[id].forEach((line, index) => {
|
|
1445
|
-
context.fillText(line, x, y + index * textSize + index * textGap);
|
|
1446
|
-
});
|
|
1447
|
-
return;
|
|
1448
|
-
}
|
|
1449
|
-
if (maxWidth == undefined || context.measureText(text).width <= maxWidth) {
|
|
1450
|
-
cachedNodeText[id] = [text];
|
|
1451
|
-
context.fillText(text, x, y);
|
|
1452
|
-
return;
|
|
1453
|
-
}
|
|
1454
|
-
const { lines } = getTextLines({
|
|
1455
|
-
context,
|
|
1456
|
-
maxWidth,
|
|
1457
|
-
text,
|
|
1458
|
-
textAlign,
|
|
1459
|
-
textColor,
|
|
1460
|
-
textFont,
|
|
1461
|
-
textSize,
|
|
1462
|
-
textStyle,
|
|
1463
|
-
textWeight,
|
|
1464
|
-
});
|
|
1465
|
-
cachedNodeText[id] = lines;
|
|
1466
1452
|
lines.forEach((line, index) => {
|
|
1467
1453
|
context.fillText(line, x, y + index * textSize + index * textGap);
|
|
1468
1454
|
});
|
|
@@ -1504,21 +1490,14 @@ function getTextLines({ context, textAlign, textColor, textFont, textStyle, text
|
|
|
1504
1490
|
}
|
|
1505
1491
|
|
|
1506
1492
|
function getDrawNode(nodeRenders, textRenders) {
|
|
1507
|
-
return function drawNode(node
|
|
1493
|
+
return function drawNode(node) {
|
|
1508
1494
|
if (!this.context || !node.x || !node.y)
|
|
1509
1495
|
return;
|
|
1510
1496
|
if (node.visible != undefined && !node.visible)
|
|
1511
1497
|
return;
|
|
1512
|
-
|
|
1513
|
-
if (
|
|
1514
|
-
|
|
1515
|
-
}
|
|
1516
|
-
else {
|
|
1517
|
-
nodeOptions = nodeIterationExtractor(node, index, this.nodes, this, this.nodeSettings.options ?? {}, nodeOptionsGetter);
|
|
1518
|
-
if (this.nodeSettings.cacheOptions) {
|
|
1519
|
-
this.nodeOptionsCache[node.id] = nodeOptions;
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1498
|
+
const nodeOptions = this.nodeOptionsCache[node.id];
|
|
1499
|
+
if (!nodeOptions)
|
|
1500
|
+
return;
|
|
1522
1501
|
if (nodeOptions.nodeDraw && nodeOptions.textDraw) {
|
|
1523
1502
|
nodeRenders.push(() => {
|
|
1524
1503
|
if (nodeOptions.nodeDraw) {
|
|
@@ -1532,13 +1511,13 @@ function getDrawNode(nodeRenders, textRenders) {
|
|
|
1532
1511
|
});
|
|
1533
1512
|
return;
|
|
1534
1513
|
}
|
|
1514
|
+
let radius = nodeOptions.radius;
|
|
1515
|
+
let width = nodeOptions.width;
|
|
1516
|
+
let height = nodeOptions.height;
|
|
1535
1517
|
let alpha = nodeOptions.alpha;
|
|
1536
1518
|
let color = nodeOptions.color;
|
|
1537
1519
|
let borderColor = nodeOptions.borderColor;
|
|
1538
1520
|
let borderWidth = nodeOptions.borderWidth;
|
|
1539
|
-
let radiusInitial = nodeOptions.radius;
|
|
1540
|
-
let widthInitial = nodeOptions.width;
|
|
1541
|
-
let heightInitial = nodeOptions.height;
|
|
1542
1521
|
let textAlpha = nodeOptions.textAlpha;
|
|
1543
1522
|
let textSize = nodeOptions.textSize;
|
|
1544
1523
|
let textShiftX = nodeOptions.textShiftX;
|
|
@@ -1585,9 +1564,9 @@ function getDrawNode(nodeRenders, textRenders) {
|
|
|
1585
1564
|
color = highlightOptions.color;
|
|
1586
1565
|
borderColor = highlightOptions.borderColor;
|
|
1587
1566
|
borderWidth = highlightOptions.borderWidth;
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1567
|
+
radius = highlightOptions.radiusInitial;
|
|
1568
|
+
width = highlightOptions.widthInitial;
|
|
1569
|
+
height = highlightOptions.heightInitial;
|
|
1591
1570
|
textSize = highlightOptions.textSize;
|
|
1592
1571
|
textShiftX = highlightOptions.textShiftX;
|
|
1593
1572
|
textShiftY = highlightOptions.textShiftY;
|
|
@@ -1634,9 +1613,9 @@ function getDrawNode(nodeRenders, textRenders) {
|
|
|
1634
1613
|
color = highlightOptions.color;
|
|
1635
1614
|
borderColor = highlightOptions.borderColor;
|
|
1636
1615
|
borderWidth = highlightOptions.borderWidth;
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1616
|
+
radius = highlightOptions.radiusInitial;
|
|
1617
|
+
width = highlightOptions.widthInitial;
|
|
1618
|
+
height = highlightOptions.heightInitial;
|
|
1640
1619
|
textSize = highlightOptions.textSize;
|
|
1641
1620
|
textShiftX = highlightOptions.textShiftX;
|
|
1642
1621
|
textShiftY = highlightOptions.textShiftY;
|
|
@@ -1645,78 +1624,6 @@ function getDrawNode(nodeRenders, textRenders) {
|
|
|
1645
1624
|
labelWeight = highlightOptions.labelWeight;
|
|
1646
1625
|
}
|
|
1647
1626
|
}
|
|
1648
|
-
/** Flex radius */
|
|
1649
|
-
const radius = nodeOptions.shape === "circle"
|
|
1650
|
-
? nodeRadiusGetter({
|
|
1651
|
-
radiusFlexible: this.nodeSettings.nodeRadiusFlexible,
|
|
1652
|
-
radiusInitial,
|
|
1653
|
-
radiusCoefficient: this.nodeSettings.nodeRadiusCoefficient,
|
|
1654
|
-
radiusFactor: this.nodeSettings.nodeRadiusFactor,
|
|
1655
|
-
linkCount: node.linkCount,
|
|
1656
|
-
})
|
|
1657
|
-
: radiusInitial;
|
|
1658
|
-
/** Flex size */
|
|
1659
|
-
let height = heightInitial;
|
|
1660
|
-
let width = widthInitial;
|
|
1661
|
-
if (nodeOptions.shape === "square") {
|
|
1662
|
-
const size = nodeSizeGetter({
|
|
1663
|
-
heightInitial,
|
|
1664
|
-
widthInitial,
|
|
1665
|
-
linkCount: node.linkCount,
|
|
1666
|
-
sizeCoefficient: this.nodeSettings.nodeSizeCoefficient,
|
|
1667
|
-
sizeFactor: this.nodeSettings.nodeSizeFactor,
|
|
1668
|
-
sizeFlexible: this.nodeSettings.nodeSizeFlexible,
|
|
1669
|
-
});
|
|
1670
|
-
width = size.width;
|
|
1671
|
-
height = size.height;
|
|
1672
|
-
}
|
|
1673
|
-
if (nodeOptions.shape === "text") {
|
|
1674
|
-
width = nodeOptions.width;
|
|
1675
|
-
const size = nodeSizeGetter({
|
|
1676
|
-
heightInitial,
|
|
1677
|
-
widthInitial: width,
|
|
1678
|
-
linkCount: node.linkCount,
|
|
1679
|
-
sizeCoefficient: this.nodeSettings.nodeSizeCoefficient,
|
|
1680
|
-
sizeFactor: this.nodeSettings.nodeSizeFactor,
|
|
1681
|
-
sizeFlexible: this.nodeSettings.nodeSizeFlexible,
|
|
1682
|
-
});
|
|
1683
|
-
labelSize *= size.additionalSizeCoefficient;
|
|
1684
|
-
}
|
|
1685
|
-
/** Size by text in textNode */
|
|
1686
|
-
if (nodeOptions.shape === "text" && nodeOptions.label) {
|
|
1687
|
-
let lines;
|
|
1688
|
-
let textNodeParameters;
|
|
1689
|
-
const cachedLines = this.cachedNodeLabel[node.id];
|
|
1690
|
-
const cachedTextNodeParameters = this.cachedTextNodeParameters[node.id];
|
|
1691
|
-
if (cachedLines != undefined && cachedTextNodeParameters != undefined) {
|
|
1692
|
-
lines = cachedLines;
|
|
1693
|
-
textNodeParameters = cachedTextNodeParameters;
|
|
1694
|
-
}
|
|
1695
|
-
else {
|
|
1696
|
-
const textInfo = getTextLines({
|
|
1697
|
-
context: this.context,
|
|
1698
|
-
text: nodeOptions.label,
|
|
1699
|
-
textAlign: nodeOptions.labelAlign,
|
|
1700
|
-
textColor: nodeOptions.labelColor,
|
|
1701
|
-
textFont: nodeOptions.labelFont,
|
|
1702
|
-
textSize: labelSize,
|
|
1703
|
-
maxWidth: nodeOptions.labelWidth,
|
|
1704
|
-
textStyle: nodeOptions.labelStyle,
|
|
1705
|
-
textWeight,
|
|
1706
|
-
});
|
|
1707
|
-
textNodeParameters = [textInfo.currentMaxSize, labelSize];
|
|
1708
|
-
lines = textInfo.lines;
|
|
1709
|
-
this.cachedNodeLabel[node.id] = lines;
|
|
1710
|
-
this.cachedTextNodeParameters[node.id] = textNodeParameters;
|
|
1711
|
-
}
|
|
1712
|
-
const textSizeCoefficient = labelSize / textNodeParameters[1];
|
|
1713
|
-
const maxSize = textNodeParameters[0] * textSizeCoefficient;
|
|
1714
|
-
height =
|
|
1715
|
-
lines.length * labelSize +
|
|
1716
|
-
(lines.length - 1) * nodeOptions.labelGap +
|
|
1717
|
-
nodeOptions.labelYPadding;
|
|
1718
|
-
width = maxSize + nodeOptions.labelXPadding;
|
|
1719
|
-
}
|
|
1720
1627
|
/** Node parameters */
|
|
1721
1628
|
node._radius = radius;
|
|
1722
1629
|
node._borderWidth = borderWidth;
|
|
@@ -1747,6 +1654,7 @@ function getDrawNode(nodeRenders, textRenders) {
|
|
|
1747
1654
|
this.context.lineWidth = borderWidth;
|
|
1748
1655
|
this.context.strokeStyle = borderColor;
|
|
1749
1656
|
this.context.fillStyle = color;
|
|
1657
|
+
const labelLines = this.cachedNodeLabel[node.id];
|
|
1750
1658
|
switch (nodeOptions.shape) {
|
|
1751
1659
|
case "circle": {
|
|
1752
1660
|
if (!node.image) {
|
|
@@ -1767,13 +1675,11 @@ function getDrawNode(nodeRenders, textRenders) {
|
|
|
1767
1675
|
this.context.stroke();
|
|
1768
1676
|
}
|
|
1769
1677
|
}
|
|
1770
|
-
if (node.label) {
|
|
1678
|
+
if (node.label && labelLines) {
|
|
1771
1679
|
this.context.globalAlpha = labelAlpha;
|
|
1772
1680
|
drawText({
|
|
1773
1681
|
context: this.context,
|
|
1774
|
-
|
|
1775
|
-
id: node.id,
|
|
1776
|
-
text: node.label,
|
|
1682
|
+
lines: labelLines,
|
|
1777
1683
|
textAlign: nodeOptions.labelAlign,
|
|
1778
1684
|
textColor: nodeOptions.labelColor,
|
|
1779
1685
|
textFont: nodeOptions.labelFont,
|
|
@@ -1781,7 +1687,6 @@ function getDrawNode(nodeRenders, textRenders) {
|
|
|
1781
1687
|
textSize: labelSize,
|
|
1782
1688
|
textStyle: nodeOptions.labelStyle,
|
|
1783
1689
|
textWeight: labelWeight,
|
|
1784
|
-
maxWidth: nodeOptions.labelWidth,
|
|
1785
1690
|
x: node.x,
|
|
1786
1691
|
y: node.y + labelSize / 3,
|
|
1787
1692
|
});
|
|
@@ -1807,13 +1712,11 @@ function getDrawNode(nodeRenders, textRenders) {
|
|
|
1807
1712
|
this.context.stroke();
|
|
1808
1713
|
}
|
|
1809
1714
|
}
|
|
1810
|
-
if (node.label) {
|
|
1715
|
+
if (node.label && labelLines) {
|
|
1811
1716
|
this.context.globalAlpha = labelAlpha;
|
|
1812
1717
|
drawText({
|
|
1813
1718
|
context: this.context,
|
|
1814
|
-
|
|
1815
|
-
id: node.id,
|
|
1816
|
-
text: node.label,
|
|
1719
|
+
lines: labelLines,
|
|
1817
1720
|
textAlign: nodeOptions.labelAlign,
|
|
1818
1721
|
textColor: nodeOptions.labelColor,
|
|
1819
1722
|
textFont: nodeOptions.labelFont,
|
|
@@ -1821,7 +1724,6 @@ function getDrawNode(nodeRenders, textRenders) {
|
|
|
1821
1724
|
textSize: labelSize,
|
|
1822
1725
|
textStyle: nodeOptions.labelStyle,
|
|
1823
1726
|
textWeight: labelWeight,
|
|
1824
|
-
maxWidth: nodeOptions.labelWidth,
|
|
1825
1727
|
x: node.x,
|
|
1826
1728
|
y: node.y + labelSize / 3,
|
|
1827
1729
|
});
|
|
@@ -1832,20 +1734,16 @@ function getDrawNode(nodeRenders, textRenders) {
|
|
|
1832
1734
|
if (this.nodeSettings.textNodeDebug) {
|
|
1833
1735
|
this.context.strokeRect(node.x - width / 2, node.y - height / 2, width, height);
|
|
1834
1736
|
}
|
|
1835
|
-
|
|
1836
|
-
if (nodeOptions.label && lines)
|
|
1737
|
+
if (nodeOptions.label && labelLines)
|
|
1837
1738
|
drawText({
|
|
1838
|
-
|
|
1839
|
-
cachedNodeText: this.cachedNodeLabel,
|
|
1739
|
+
lines: labelLines,
|
|
1840
1740
|
context: this.context,
|
|
1841
|
-
text: nodeOptions.label,
|
|
1842
1741
|
textAlign: nodeOptions.labelAlign,
|
|
1843
1742
|
textColor: nodeOptions.labelColor,
|
|
1844
1743
|
textFont: nodeOptions.labelFont,
|
|
1845
1744
|
textSize: labelSize,
|
|
1846
1745
|
x: node.x,
|
|
1847
|
-
y: node.y + textSize / 4 - (
|
|
1848
|
-
maxWidth: nodeOptions.labelWidth,
|
|
1746
|
+
y: node.y + textSize / 4 - (labelLines.length - 1) * (textSize / 2),
|
|
1849
1747
|
textStyle: nodeOptions.labelStyle,
|
|
1850
1748
|
textWeight,
|
|
1851
1749
|
textGap: nodeOptions.labelGap,
|
|
@@ -1882,7 +1780,8 @@ function getDrawNode(nodeRenders, textRenders) {
|
|
|
1882
1780
|
});
|
|
1883
1781
|
}
|
|
1884
1782
|
/** Text draw */
|
|
1885
|
-
|
|
1783
|
+
const textLines = this.cachedNodeText[node.id];
|
|
1784
|
+
if (nodeOptions.textVisible && nodeOptions.text && textLines) {
|
|
1886
1785
|
textRenders.push(() => {
|
|
1887
1786
|
if (nodeOptions.textDraw) {
|
|
1888
1787
|
nodeOptions.textDraw.bind(this)(node, {
|
|
@@ -1910,17 +1809,14 @@ function getDrawNode(nodeRenders, textRenders) {
|
|
|
1910
1809
|
y += height / 2;
|
|
1911
1810
|
}
|
|
1912
1811
|
drawText({
|
|
1913
|
-
|
|
1914
|
-
cachedNodeText: this.cachedNodeText,
|
|
1812
|
+
lines: textLines,
|
|
1915
1813
|
context: this.context,
|
|
1916
|
-
text: nodeOptions.text,
|
|
1917
1814
|
textAlign: nodeOptions.textAlign,
|
|
1918
1815
|
textColor: nodeOptions.textColor,
|
|
1919
1816
|
textFont: nodeOptions.textFont,
|
|
1920
1817
|
textSize,
|
|
1921
1818
|
x: node.x + textShiftX,
|
|
1922
1819
|
y,
|
|
1923
|
-
maxWidth: nodeOptions.textWidth,
|
|
1924
1820
|
textStyle: nodeOptions.textStyle,
|
|
1925
1821
|
textWeight,
|
|
1926
1822
|
textGap: nodeOptions.textGap,
|
|
@@ -1944,29 +1840,42 @@ function getDrawNode(nodeRenders, textRenders) {
|
|
|
1944
1840
|
}
|
|
1945
1841
|
|
|
1946
1842
|
function initDraw() {
|
|
1947
|
-
|
|
1948
|
-
|
|
1843
|
+
let hasHighlight = false;
|
|
1844
|
+
function calculateHighlight(recursive) {
|
|
1845
|
+
if (hasHighlight && !recursive)
|
|
1846
|
+
return;
|
|
1847
|
+
/** animation up */
|
|
1949
1848
|
if (!this.highlightWorking && this.highlightProgress > 0) {
|
|
1950
1849
|
const highlightDownStep = 1 / this.highlightSettings.highlightDownFrames;
|
|
1951
1850
|
this.highlightProgress -= highlightDownStep;
|
|
1952
1851
|
if (!this.simulationWorking) {
|
|
1953
|
-
|
|
1852
|
+
hasHighlight = true;
|
|
1853
|
+
return void requestAnimationFrame(() => this.draw(true));
|
|
1954
1854
|
}
|
|
1955
|
-
if (!this.linkSettings.particles)
|
|
1855
|
+
if (!this.linkSettings.particles) {
|
|
1856
|
+
hasHighlight = false;
|
|
1956
1857
|
return;
|
|
1858
|
+
}
|
|
1957
1859
|
}
|
|
1860
|
+
/** animation down */
|
|
1958
1861
|
if (this.highlightWorking && this.highlightProgress < 1) {
|
|
1959
1862
|
const highlightUpStep = 1 / this.highlightSettings.highlightUpFrames;
|
|
1960
1863
|
this.highlightProgress += highlightUpStep;
|
|
1961
1864
|
if (!this.simulationWorking) {
|
|
1962
|
-
|
|
1865
|
+
hasHighlight = true;
|
|
1866
|
+
return void requestAnimationFrame(() => this.draw(true));
|
|
1963
1867
|
}
|
|
1964
|
-
if (!this.linkSettings.particles)
|
|
1868
|
+
if (!this.linkSettings.particles) {
|
|
1869
|
+
hasHighlight = false;
|
|
1965
1870
|
return;
|
|
1871
|
+
}
|
|
1966
1872
|
}
|
|
1873
|
+
/** animation active */
|
|
1967
1874
|
if (this.linkSettings.particles && this.highlightWorking && !this.simulationWorking) {
|
|
1968
|
-
|
|
1875
|
+
hasHighlight = true;
|
|
1876
|
+
return void requestAnimationFrame(() => this.draw(true));
|
|
1969
1877
|
}
|
|
1878
|
+
/** animation stop */
|
|
1970
1879
|
if (!this.highlightWorking && this.highlightProgress <= 0) {
|
|
1971
1880
|
if (this.highlightedNeighbors || this.highlightedNode || this.highlightedLink) {
|
|
1972
1881
|
this.highlightedNeighbors = null;
|
|
@@ -1974,13 +1883,14 @@ function initDraw() {
|
|
|
1974
1883
|
this.highlightedLink = null;
|
|
1975
1884
|
this.particles = {};
|
|
1976
1885
|
if (!this.simulationWorking) {
|
|
1977
|
-
|
|
1886
|
+
hasHighlight = true;
|
|
1887
|
+
return void requestAnimationFrame(() => this.draw(true));
|
|
1978
1888
|
}
|
|
1979
1889
|
}
|
|
1980
1890
|
}
|
|
1981
|
-
|
|
1891
|
+
hasHighlight = false;
|
|
1982
1892
|
}
|
|
1983
|
-
function draw() {
|
|
1893
|
+
function draw(recursive = false) {
|
|
1984
1894
|
if (!this.context)
|
|
1985
1895
|
return;
|
|
1986
1896
|
if (this.listeners.onDraw) {
|
|
@@ -2001,7 +1911,7 @@ function initDraw() {
|
|
|
2001
1911
|
textRenders.forEach((render) => render());
|
|
2002
1912
|
this.context.restore();
|
|
2003
1913
|
this.listeners.onDrawFinished?.call?.(this);
|
|
2004
|
-
calculateHighlight.bind(this)();
|
|
1914
|
+
calculateHighlight.bind(this)(recursive);
|
|
2005
1915
|
}
|
|
2006
1916
|
if (this.graphSettings.showDrawTime) {
|
|
2007
1917
|
return setDrawTime(draw.bind(this), this.graphSettings.showDrawTimeEveryTick);
|
|
@@ -2059,7 +1969,7 @@ function initPointer() {
|
|
|
2059
1969
|
this.highlightedLink = null;
|
|
2060
1970
|
this.highlightedNeighbors = new Set(this.highlightedNode?.neighbors ?? []);
|
|
2061
1971
|
this.highlightWorking = true;
|
|
2062
|
-
if (!this.simulationWorking
|
|
1972
|
+
if (!this.simulationWorking)
|
|
2063
1973
|
requestAnimationFrame(() => {
|
|
2064
1974
|
this.draw();
|
|
2065
1975
|
});
|
|
@@ -2074,14 +1984,14 @@ function initPointer() {
|
|
|
2074
1984
|
this.highlightedNode = null;
|
|
2075
1985
|
this.highlightedNeighbors = new Set([currentLink.source.id, currentLink.target.id]);
|
|
2076
1986
|
this.highlightWorking = true;
|
|
2077
|
-
if (!this.simulationWorking
|
|
1987
|
+
if (!this.simulationWorking)
|
|
2078
1988
|
requestAnimationFrame(() => {
|
|
2079
1989
|
this.draw();
|
|
2080
1990
|
});
|
|
2081
1991
|
}
|
|
2082
1992
|
else if (!currentNode && !currentLink && (this.highlightedNode || this.highlightedLink)) {
|
|
2083
1993
|
this.highlightWorking = false;
|
|
2084
|
-
if (!this.simulationWorking
|
|
1994
|
+
if (!this.simulationWorking)
|
|
2085
1995
|
requestAnimationFrame(() => {
|
|
2086
1996
|
this.draw();
|
|
2087
1997
|
});
|
|
@@ -2335,9 +2245,12 @@ function initCollideForce(forceUpdate) {
|
|
|
2335
2245
|
const radius = nodeRadiusGetter({
|
|
2336
2246
|
radiusFlexible: this.nodeSettings.nodeRadiusFlexible,
|
|
2337
2247
|
radiusInitial: nodeOptions.radius,
|
|
2338
|
-
radiusCoefficient: this.nodeSettings.nodeRadiusCoefficient,
|
|
2339
|
-
radiusFactor: this.nodeSettings.nodeRadiusFactor,
|
|
2340
2248
|
linkCount: node.linkCount,
|
|
2249
|
+
radiusIncrementByStep: this.nodeSettings.nodeRadiusIncrementByStep,
|
|
2250
|
+
radiusLinkCountForStep: this.nodeSettings.nodeRadiusLinkCountForStep,
|
|
2251
|
+
radiusMaxLinearSteps: this.nodeSettings.nodeRadiusMaxLinearSteps,
|
|
2252
|
+
radiusLogFactor: this.nodeSettings.nodeRadiusLogFactor,
|
|
2253
|
+
radiusLinkCountDividerForLog: this.nodeSettings.nodeRadiusLinkCountDividerForLog,
|
|
2341
2254
|
});
|
|
2342
2255
|
return radius + this.forceSettings.collideAdditionalRadius;
|
|
2343
2256
|
}
|
|
@@ -2346,9 +2259,12 @@ function initCollideForce(forceUpdate) {
|
|
|
2346
2259
|
heightInitial: nodeOptions.width,
|
|
2347
2260
|
widthInitial: nodeOptions.height,
|
|
2348
2261
|
linkCount: node.linkCount,
|
|
2349
|
-
sizeCoefficient: this.nodeSettings.nodeSizeCoefficient,
|
|
2350
|
-
sizeFactor: this.nodeSettings.nodeSizeFactor,
|
|
2351
2262
|
sizeFlexible: this.nodeSettings.nodeSizeFlexible,
|
|
2263
|
+
sizeIncrementByStep: this.nodeSettings.nodeSizeIncrementByStep,
|
|
2264
|
+
sizeLinkCountForStep: this.nodeSettings.nodeSizeLinkCountForStep,
|
|
2265
|
+
sizeMaxLinearSteps: this.nodeSettings.nodeSizeMaxLinearSteps,
|
|
2266
|
+
sizeLogFactor: this.nodeSettings.nodeSizeLogFactor,
|
|
2267
|
+
sizeLinkCountDividerForLog: this.nodeSettings.nodeSizeLinkCountDividerForLog,
|
|
2352
2268
|
});
|
|
2353
2269
|
return (Math.sqrt(width ** 2 + height ** 2) / 2 +
|
|
2354
2270
|
this.forceSettings.collideAdditionalRadius);
|
|
@@ -2358,9 +2274,12 @@ function initCollideForce(forceUpdate) {
|
|
|
2358
2274
|
heightInitial: nodeOptions.width,
|
|
2359
2275
|
widthInitial: nodeOptions.height,
|
|
2360
2276
|
linkCount: node.linkCount,
|
|
2361
|
-
sizeCoefficient: this.nodeSettings.nodeSizeCoefficient,
|
|
2362
|
-
sizeFactor: this.nodeSettings.nodeSizeFactor,
|
|
2363
2277
|
sizeFlexible: this.nodeSettings.nodeSizeFlexible,
|
|
2278
|
+
sizeIncrementByStep: this.nodeSettings.nodeSizeIncrementByStep,
|
|
2279
|
+
sizeLinkCountForStep: this.nodeSettings.nodeSizeLinkCountForStep,
|
|
2280
|
+
sizeMaxLinearSteps: this.nodeSettings.nodeSizeMaxLinearSteps,
|
|
2281
|
+
sizeLogFactor: this.nodeSettings.nodeSizeLogFactor,
|
|
2282
|
+
sizeLinkCountDividerForLog: this.nodeSettings.nodeSizeLinkCountDividerForLog,
|
|
2364
2283
|
});
|
|
2365
2284
|
if (this.context && nodeOptions.text) {
|
|
2366
2285
|
const textInfo = getTextLines({
|
|
@@ -2390,8 +2309,11 @@ function initCollideForce(forceUpdate) {
|
|
|
2390
2309
|
const radius = nodeRadiusGetter({
|
|
2391
2310
|
radiusFlexible: this.nodeSettings.nodeRadiusFlexible,
|
|
2392
2311
|
radiusInitial: nodeOptions.radius,
|
|
2393
|
-
|
|
2394
|
-
|
|
2312
|
+
radiusIncrementByStep: this.nodeSettings.nodeRadiusIncrementByStep,
|
|
2313
|
+
radiusLinkCountForStep: this.nodeSettings.nodeRadiusLinkCountForStep,
|
|
2314
|
+
radiusMaxLinearSteps: this.nodeSettings.nodeRadiusMaxLinearSteps,
|
|
2315
|
+
radiusLogFactor: this.nodeSettings.nodeRadiusLogFactor,
|
|
2316
|
+
radiusLinkCountDividerForLog: this.nodeSettings.nodeRadiusLinkCountDividerForLog,
|
|
2395
2317
|
linkCount: node.linkCount,
|
|
2396
2318
|
});
|
|
2397
2319
|
return radius + this.forceSettings.collideAdditionalRadius;
|
|
@@ -2404,6 +2326,145 @@ function initCollideForce(forceUpdate) {
|
|
|
2404
2326
|
}
|
|
2405
2327
|
}
|
|
2406
2328
|
|
|
2329
|
+
function updateLinkCache() {
|
|
2330
|
+
this.linkOptionsCache = {};
|
|
2331
|
+
for (let i = 0; i < this.links.length; i++) {
|
|
2332
|
+
const link = this.links[i];
|
|
2333
|
+
const { sourceId, targetId } = extractLinkPointIds(link);
|
|
2334
|
+
const linkOptions = linkIterationExtractor(link, i, this.links, this, this.linkSettings.options ?? {}, linkOptionsGetter);
|
|
2335
|
+
const id = `${targetId}${sourceId}`;
|
|
2336
|
+
this.linkOptionsCache[id] = linkOptions;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
function updateNodeCache() {
|
|
2341
|
+
this.nodeOptionsCache = {};
|
|
2342
|
+
if (!this.context)
|
|
2343
|
+
return;
|
|
2344
|
+
for (let i = 0; i < this.nodes.length; i++) {
|
|
2345
|
+
const node = this.nodes[i];
|
|
2346
|
+
const nodeOptions = nodeIterationExtractor(node, i, this.nodes, this, this.nodeSettings.options ?? {}, nodeOptionsGetter);
|
|
2347
|
+
const radius = nodeOptions.shape === "circle"
|
|
2348
|
+
? nodeRadiusGetter({
|
|
2349
|
+
radiusFlexible: this.nodeSettings.nodeRadiusFlexible,
|
|
2350
|
+
radiusInitial: nodeOptions.radius,
|
|
2351
|
+
radiusIncrementByStep: this.nodeSettings.nodeRadiusIncrementByStep,
|
|
2352
|
+
radiusLinkCountForStep: this.nodeSettings.nodeRadiusLinkCountForStep,
|
|
2353
|
+
radiusMaxLinearSteps: this.nodeSettings.nodeRadiusMaxLinearSteps,
|
|
2354
|
+
radiusLogFactor: this.nodeSettings.nodeRadiusLogFactor,
|
|
2355
|
+
radiusLinkCountDividerForLog: this.nodeSettings.nodeRadiusLinkCountDividerForLog,
|
|
2356
|
+
linkCount: node.linkCount,
|
|
2357
|
+
})
|
|
2358
|
+
: nodeOptions.radius;
|
|
2359
|
+
let width = nodeOptions.width;
|
|
2360
|
+
let height = nodeOptions.height;
|
|
2361
|
+
let labelSize = nodeOptions.labelSize;
|
|
2362
|
+
if (nodeOptions.shape === "square") {
|
|
2363
|
+
const size = nodeSizeGetter({
|
|
2364
|
+
heightInitial: nodeOptions.height,
|
|
2365
|
+
widthInitial: nodeOptions.width,
|
|
2366
|
+
linkCount: node.linkCount,
|
|
2367
|
+
sizeFlexible: this.nodeSettings.nodeSizeFlexible,
|
|
2368
|
+
sizeIncrementByStep: this.nodeSettings.nodeSizeIncrementByStep,
|
|
2369
|
+
sizeLinkCountForStep: this.nodeSettings.nodeSizeLinkCountForStep,
|
|
2370
|
+
sizeMaxLinearSteps: this.nodeSettings.nodeSizeMaxLinearSteps,
|
|
2371
|
+
sizeLogFactor: this.nodeSettings.nodeSizeLogFactor,
|
|
2372
|
+
sizeLinkCountDividerForLog: this.nodeSettings.nodeSizeLinkCountDividerForLog,
|
|
2373
|
+
});
|
|
2374
|
+
width = size.width;
|
|
2375
|
+
height = size.height;
|
|
2376
|
+
}
|
|
2377
|
+
if (nodeOptions.shape === "text") {
|
|
2378
|
+
width = nodeOptions.width;
|
|
2379
|
+
const size = nodeSizeGetter({
|
|
2380
|
+
heightInitial: nodeOptions.height,
|
|
2381
|
+
widthInitial: width,
|
|
2382
|
+
linkCount: node.linkCount,
|
|
2383
|
+
sizeFlexible: this.nodeSettings.nodeSizeFlexible,
|
|
2384
|
+
sizeIncrementByStep: this.nodeSettings.nodeSizeIncrementByStep,
|
|
2385
|
+
sizeLinkCountForStep: this.nodeSettings.nodeSizeLinkCountForStep,
|
|
2386
|
+
sizeMaxLinearSteps: this.nodeSettings.nodeSizeMaxLinearSteps,
|
|
2387
|
+
sizeLogFactor: this.nodeSettings.nodeSizeLogFactor,
|
|
2388
|
+
sizeLinkCountDividerForLog: this.nodeSettings.nodeSizeLinkCountDividerForLog,
|
|
2389
|
+
});
|
|
2390
|
+
labelSize *= size.additionalSizeCoefficient;
|
|
2391
|
+
}
|
|
2392
|
+
/** label in not text shape */
|
|
2393
|
+
if (nodeOptions.shape !== "text" && nodeOptions.label) {
|
|
2394
|
+
this.context.font = `${nodeOptions.labelStyle} normal ${nodeOptions.labelWeight} ${nodeOptions.labelSize}px ${nodeOptions.labelFont}`;
|
|
2395
|
+
this.context.fillStyle = nodeOptions.labelColor;
|
|
2396
|
+
this.context.textAlign = nodeOptions.labelAlign;
|
|
2397
|
+
if (nodeOptions.labelWidth == undefined ||
|
|
2398
|
+
this.context.measureText(nodeOptions.label).width <= nodeOptions.labelWidth) {
|
|
2399
|
+
this.cachedNodeLabel[node.id] = [nodeOptions.label];
|
|
2400
|
+
}
|
|
2401
|
+
const { lines } = getTextLines({
|
|
2402
|
+
context: this.context,
|
|
2403
|
+
maxWidth: nodeOptions.labelWidth,
|
|
2404
|
+
text: nodeOptions.label,
|
|
2405
|
+
textAlign: nodeOptions.labelAlign,
|
|
2406
|
+
textColor: nodeOptions.labelColor,
|
|
2407
|
+
textFont: nodeOptions.labelFont,
|
|
2408
|
+
textSize: nodeOptions.labelSize,
|
|
2409
|
+
textStyle: nodeOptions.labelStyle,
|
|
2410
|
+
textWeight: nodeOptions.labelWeight,
|
|
2411
|
+
});
|
|
2412
|
+
this.cachedNodeLabel[node.id] = lines;
|
|
2413
|
+
}
|
|
2414
|
+
/** label in text shape */
|
|
2415
|
+
if (nodeOptions.shape === "text" && nodeOptions.label) {
|
|
2416
|
+
const textInfo = getTextLines({
|
|
2417
|
+
context: this.context,
|
|
2418
|
+
text: nodeOptions.label,
|
|
2419
|
+
textAlign: nodeOptions.labelAlign,
|
|
2420
|
+
textColor: nodeOptions.labelColor,
|
|
2421
|
+
textFont: nodeOptions.labelFont,
|
|
2422
|
+
textSize: labelSize,
|
|
2423
|
+
maxWidth: nodeOptions.labelWidth,
|
|
2424
|
+
textStyle: nodeOptions.labelStyle,
|
|
2425
|
+
textWeight: nodeOptions.textWeight,
|
|
2426
|
+
});
|
|
2427
|
+
const textNodeParameters = [textInfo.currentMaxSize, labelSize];
|
|
2428
|
+
const lines = textInfo.lines;
|
|
2429
|
+
const textSizeCoefficient = labelSize / textNodeParameters[1];
|
|
2430
|
+
const maxSize = textNodeParameters[0] * textSizeCoefficient;
|
|
2431
|
+
height =
|
|
2432
|
+
lines.length * labelSize +
|
|
2433
|
+
(lines.length - 1) * nodeOptions.labelGap +
|
|
2434
|
+
nodeOptions.labelYPadding;
|
|
2435
|
+
width = maxSize + nodeOptions.labelXPadding;
|
|
2436
|
+
this.cachedNodeLabel[node.id] = lines;
|
|
2437
|
+
}
|
|
2438
|
+
nodeOptions.width = width;
|
|
2439
|
+
nodeOptions.height = height;
|
|
2440
|
+
nodeOptions.radius = radius;
|
|
2441
|
+
nodeOptions.labelSize = labelSize;
|
|
2442
|
+
/** text */
|
|
2443
|
+
if (nodeOptions.text) {
|
|
2444
|
+
this.context.font = `${nodeOptions.textStyle} normal ${nodeOptions.textWeight} ${nodeOptions.textSize}px ${nodeOptions.textFont}`;
|
|
2445
|
+
this.context.fillStyle = nodeOptions.textColor;
|
|
2446
|
+
this.context.textAlign = nodeOptions.textAlign;
|
|
2447
|
+
if (nodeOptions.textWidth == undefined ||
|
|
2448
|
+
this.context.measureText(nodeOptions.text).width <= nodeOptions.textWidth) {
|
|
2449
|
+
this.cachedNodeText[node.id] = [nodeOptions.text];
|
|
2450
|
+
}
|
|
2451
|
+
const { lines } = getTextLines({
|
|
2452
|
+
context: this.context,
|
|
2453
|
+
maxWidth: nodeOptions.textWidth,
|
|
2454
|
+
text: nodeOptions.text,
|
|
2455
|
+
textAlign: nodeOptions.textAlign,
|
|
2456
|
+
textColor: nodeOptions.textColor,
|
|
2457
|
+
textFont: nodeOptions.textFont,
|
|
2458
|
+
textSize: nodeOptions.textSize,
|
|
2459
|
+
textStyle: nodeOptions.textStyle,
|
|
2460
|
+
textWeight: nodeOptions.textWeight,
|
|
2461
|
+
});
|
|
2462
|
+
this.cachedNodeText[node.id] = lines;
|
|
2463
|
+
}
|
|
2464
|
+
this.nodeOptionsCache[node.id] = nodeOptions;
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2407
2468
|
function initZoom(currentZoom) {
|
|
2408
2469
|
if (!this.area)
|
|
2409
2470
|
throw new Error("bad init data");
|
|
@@ -2412,8 +2473,8 @@ function initZoom(currentZoom) {
|
|
|
2412
2473
|
.on("zoom", (event) => {
|
|
2413
2474
|
this.listeners.onZoom?.call?.(this, event);
|
|
2414
2475
|
this.areaTransform = event.transform;
|
|
2415
|
-
this
|
|
2416
|
-
this
|
|
2476
|
+
updateLinkCache.call(this);
|
|
2477
|
+
updateNodeCache.call(this);
|
|
2417
2478
|
if (!this.simulationWorking && !this.highlightWorking)
|
|
2418
2479
|
requestAnimationFrame(() => this.draw());
|
|
2419
2480
|
});
|
|
@@ -2460,7 +2521,6 @@ class GraphCanvas {
|
|
|
2460
2521
|
eventAbortController;
|
|
2461
2522
|
cachedNodeText = {};
|
|
2462
2523
|
cachedNodeLabel = {};
|
|
2463
|
-
cachedTextNodeParameters = {};
|
|
2464
2524
|
linkOptionsCache = {};
|
|
2465
2525
|
nodeOptionsCache = {};
|
|
2466
2526
|
isDragging = false;
|
|
@@ -2469,7 +2529,6 @@ class GraphCanvas {
|
|
|
2469
2529
|
highlightedNeighbors = null;
|
|
2470
2530
|
highlightProgress = 1;
|
|
2471
2531
|
highlightWorking = false;
|
|
2472
|
-
highlightDrawing = false;
|
|
2473
2532
|
get simulationWorking() {
|
|
2474
2533
|
const simulationAlpha = this.simulation?.alpha?.() ?? 0;
|
|
2475
2534
|
const simulationAlphaMin = this.simulation?.alphaMin?.() ?? 0;
|
|
@@ -2504,15 +2563,15 @@ class GraphCanvas {
|
|
|
2504
2563
|
nodes: this.nodes,
|
|
2505
2564
|
};
|
|
2506
2565
|
}
|
|
2507
|
-
changeData(options, alpha) {
|
|
2566
|
+
changeData(options, alpha = 0.5, clearCache = true) {
|
|
2508
2567
|
if (options.links != undefined)
|
|
2509
2568
|
this.links = options.links;
|
|
2510
2569
|
if (options.nodes != undefined)
|
|
2511
2570
|
this.nodes = options.nodes;
|
|
2512
2571
|
if (options.nodes != undefined || options.links != undefined)
|
|
2513
|
-
this.updateData(alpha);
|
|
2572
|
+
this.updateData(alpha, clearCache);
|
|
2514
2573
|
}
|
|
2515
|
-
changeSettings(options) {
|
|
2574
|
+
changeSettings(options, clearCache = true) {
|
|
2516
2575
|
if (options.graphSettings) {
|
|
2517
2576
|
this.graphSettings = graphSettingsGetter(options.graphSettings, this.graphSettings);
|
|
2518
2577
|
this.draw = initDraw.call(this);
|
|
@@ -2523,22 +2582,21 @@ class GraphCanvas {
|
|
|
2523
2582
|
}
|
|
2524
2583
|
if (options.highlightSettings) {
|
|
2525
2584
|
this.highlightSettings = highlightSettingsGetter(options.highlightSettings, this.highlightSettings);
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
this.cachedTextNodeParameters = {};
|
|
2530
|
-
this.nodeOptionsCache = {};
|
|
2585
|
+
if (clearCache) {
|
|
2586
|
+
this.clearCache(["nodeOptionsCache", "linkOptionsCache"]);
|
|
2587
|
+
}
|
|
2531
2588
|
}
|
|
2532
2589
|
if (options.linkSettings) {
|
|
2533
2590
|
this.linkSettings = linkSettingsGetter(options.linkSettings, this.linkSettings);
|
|
2534
|
-
|
|
2591
|
+
if (clearCache) {
|
|
2592
|
+
this.clearCache(["linkOptionsCache"]);
|
|
2593
|
+
}
|
|
2535
2594
|
}
|
|
2536
2595
|
if (options.nodeSettings) {
|
|
2537
2596
|
this.nodeSettings = nodeSettingsGetter(options.nodeSettings, this.nodeSettings);
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
this.nodeOptionsCache = {};
|
|
2597
|
+
if (clearCache) {
|
|
2598
|
+
this.clearCache(["nodeOptionsCache"]);
|
|
2599
|
+
}
|
|
2542
2600
|
initCollideForce.call(this, true);
|
|
2543
2601
|
}
|
|
2544
2602
|
if (options.forceSettings) {
|
|
@@ -2564,16 +2622,18 @@ class GraphCanvas {
|
|
|
2564
2622
|
}
|
|
2565
2623
|
clearCache(keys) {
|
|
2566
2624
|
if (!keys) {
|
|
2567
|
-
this
|
|
2568
|
-
this
|
|
2569
|
-
this.cachedNodeText = {};
|
|
2570
|
-
this.cachedNodeLabel = {};
|
|
2571
|
-
this.cachedTextNodeParameters = {};
|
|
2625
|
+
updateNodeCache.call(this);
|
|
2626
|
+
updateLinkCache.call(this);
|
|
2572
2627
|
}
|
|
2573
2628
|
else {
|
|
2574
2629
|
for (let i = 0; i < keys.length; i++) {
|
|
2575
2630
|
const key = keys[i];
|
|
2576
|
-
|
|
2631
|
+
if (key === "nodeOptionsCache") {
|
|
2632
|
+
updateNodeCache.call(this);
|
|
2633
|
+
}
|
|
2634
|
+
else {
|
|
2635
|
+
updateLinkCache.call(this);
|
|
2636
|
+
}
|
|
2577
2637
|
}
|
|
2578
2638
|
}
|
|
2579
2639
|
}
|
|
@@ -2631,10 +2691,11 @@ class GraphCanvas {
|
|
|
2631
2691
|
this.highlightedNeighbors = null;
|
|
2632
2692
|
this.highlightProgress = 0;
|
|
2633
2693
|
this.highlightWorking = false;
|
|
2634
|
-
this.highlightDrawing = false;
|
|
2635
2694
|
}
|
|
2636
|
-
updateData(alpha) {
|
|
2637
|
-
|
|
2695
|
+
updateData(alpha = 0.5, clearCache = true) {
|
|
2696
|
+
if (clearCache) {
|
|
2697
|
+
this.clearCache();
|
|
2698
|
+
}
|
|
2638
2699
|
if (this.simulation) {
|
|
2639
2700
|
initCollideForce.call(this, false);
|
|
2640
2701
|
this.simulation
|
|
@@ -2650,12 +2711,14 @@ class GraphCanvas {
|
|
|
2650
2711
|
.iterations(this.forceSettings.forces && this.forceSettings.linkForce
|
|
2651
2712
|
? this.forceSettings.linkIterations
|
|
2652
2713
|
: 0))
|
|
2653
|
-
.alpha(alpha
|
|
2714
|
+
.alpha(alpha)
|
|
2654
2715
|
.restart();
|
|
2655
2716
|
}
|
|
2656
2717
|
}
|
|
2657
2718
|
init() {
|
|
2658
2719
|
initArea.call(this);
|
|
2720
|
+
updateNodeCache.call(this);
|
|
2721
|
+
updateLinkCache.call(this);
|
|
2659
2722
|
initSimulation.call(this);
|
|
2660
2723
|
initDnd.call(this);
|
|
2661
2724
|
initZoom.call(this);
|
|
@@ -3246,12 +3309,6 @@ const HIGHLIGHT_BY_LINK_FOR_ARROW_CONTROLS = [
|
|
|
3246
3309
|
];
|
|
3247
3310
|
|
|
3248
3311
|
const LINK_SETTINGS_CONTROLS = [
|
|
3249
|
-
{
|
|
3250
|
-
id: "cacheOptions",
|
|
3251
|
-
type: "checkbox",
|
|
3252
|
-
label: "Кеширование вычисляемых настроек",
|
|
3253
|
-
initialValue: LINK_SETTINGS.cacheOptions,
|
|
3254
|
-
},
|
|
3255
3312
|
{
|
|
3256
3313
|
id: "prettyDraw",
|
|
3257
3314
|
type: "checkbox",
|
|
@@ -3459,12 +3516,6 @@ const LINK_OPTIONS_PARTICLE_CONTROLS = [
|
|
|
3459
3516
|
];
|
|
3460
3517
|
|
|
3461
3518
|
const NODE_SETTINGS_CONTROLS = [
|
|
3462
|
-
{
|
|
3463
|
-
id: "cacheOptions",
|
|
3464
|
-
type: "checkbox",
|
|
3465
|
-
initialValue: NODE_SETTINGS.cacheOptions,
|
|
3466
|
-
label: "Кеширование вычисляемых настроек",
|
|
3467
|
-
},
|
|
3468
3519
|
{
|
|
3469
3520
|
id: "textNodeDebug",
|
|
3470
3521
|
type: "checkbox",
|
|
@@ -3475,49 +3526,103 @@ const NODE_SETTINGS_CONTROLS = [
|
|
|
3475
3526
|
id: "nodeRadiusFlexible",
|
|
3476
3527
|
type: "checkbox",
|
|
3477
3528
|
initialValue: NODE_SETTINGS.nodeRadiusFlexible,
|
|
3478
|
-
label: "Гибкий радиус
|
|
3529
|
+
label: "Гибкий радиус",
|
|
3479
3530
|
},
|
|
3480
3531
|
{
|
|
3481
|
-
id: "
|
|
3482
|
-
initialValue: NODE_SETTINGS.
|
|
3532
|
+
id: "nodeRadiusLinkCountForStep",
|
|
3533
|
+
initialValue: NODE_SETTINGS.nodeRadiusLinkCountForStep,
|
|
3483
3534
|
max: 100,
|
|
3484
3535
|
min: 0.1,
|
|
3485
3536
|
step: 0.1,
|
|
3486
3537
|
type: "range",
|
|
3487
|
-
label: "Количество связей для увеличения
|
|
3538
|
+
label: "Количество связей для увеличения линейного шага радиуса",
|
|
3488
3539
|
},
|
|
3489
3540
|
{
|
|
3490
|
-
id: "
|
|
3491
|
-
initialValue: NODE_SETTINGS.
|
|
3541
|
+
id: "nodeRadiusIncrementByStep",
|
|
3542
|
+
initialValue: NODE_SETTINGS.nodeRadiusIncrementByStep,
|
|
3492
3543
|
max: 50,
|
|
3493
3544
|
min: 0.1,
|
|
3494
3545
|
step: 0.1,
|
|
3495
3546
|
type: "range",
|
|
3496
|
-
label: "
|
|
3547
|
+
label: "Размер шага линейного увеличения радиуса",
|
|
3548
|
+
},
|
|
3549
|
+
{
|
|
3550
|
+
id: "nodeRadiusMaxLinearSteps",
|
|
3551
|
+
initialValue: NODE_SETTINGS.nodeRadiusMaxLinearSteps,
|
|
3552
|
+
max: 50,
|
|
3553
|
+
min: 1,
|
|
3554
|
+
step: 1,
|
|
3555
|
+
type: "range",
|
|
3556
|
+
label: "Максимальное число шагов линейного увеличения радиуса",
|
|
3557
|
+
},
|
|
3558
|
+
{
|
|
3559
|
+
id: "nodeRadiusLogFactor",
|
|
3560
|
+
initialValue: NODE_SETTINGS.nodeRadiusLogFactor,
|
|
3561
|
+
max: 50,
|
|
3562
|
+
min: 1,
|
|
3563
|
+
step: 1,
|
|
3564
|
+
type: "range",
|
|
3565
|
+
label: "Число умножаемое на логарифм от количества связей для увеличения радиуса",
|
|
3566
|
+
},
|
|
3567
|
+
{
|
|
3568
|
+
id: "nodeRadiusLinkCountDividerForLog",
|
|
3569
|
+
initialValue: NODE_SETTINGS.nodeRadiusLinkCountDividerForLog,
|
|
3570
|
+
max: 50,
|
|
3571
|
+
min: 1,
|
|
3572
|
+
step: 1,
|
|
3573
|
+
type: "range",
|
|
3574
|
+
label: "Делитель количества связей для вычисления логарифма увеличения радиуса.",
|
|
3497
3575
|
},
|
|
3498
3576
|
{
|
|
3499
3577
|
id: "nodeSizeFlexible",
|
|
3500
3578
|
type: "checkbox",
|
|
3501
3579
|
initialValue: NODE_SETTINGS.nodeSizeFlexible,
|
|
3502
|
-
label: "Гибкий размер
|
|
3580
|
+
label: "Гибкий размер",
|
|
3581
|
+
},
|
|
3582
|
+
{
|
|
3583
|
+
id: "nodeSizeLinkCountForStep",
|
|
3584
|
+
initialValue: NODE_SETTINGS.nodeSizeLinkCountForStep,
|
|
3585
|
+
max: 100,
|
|
3586
|
+
min: 0.1,
|
|
3587
|
+
step: 0.1,
|
|
3588
|
+
type: "range",
|
|
3589
|
+
label: "Количество связей для увеличения линейного шага размера",
|
|
3503
3590
|
},
|
|
3504
3591
|
{
|
|
3505
|
-
id: "
|
|
3506
|
-
initialValue: NODE_SETTINGS.
|
|
3592
|
+
id: "nodeSizeIncrementByStep",
|
|
3593
|
+
initialValue: NODE_SETTINGS.nodeSizeIncrementByStep,
|
|
3507
3594
|
max: 50,
|
|
3508
3595
|
min: 0.1,
|
|
3509
3596
|
step: 0.1,
|
|
3510
3597
|
type: "range",
|
|
3511
|
-
label: "
|
|
3598
|
+
label: "Размер шага линейного увеличения размера",
|
|
3512
3599
|
},
|
|
3513
3600
|
{
|
|
3514
|
-
id: "
|
|
3515
|
-
initialValue: NODE_SETTINGS.
|
|
3516
|
-
max:
|
|
3517
|
-
min:
|
|
3518
|
-
step:
|
|
3601
|
+
id: "nodeSizeMaxLinearSteps",
|
|
3602
|
+
initialValue: NODE_SETTINGS.nodeSizeMaxLinearSteps,
|
|
3603
|
+
max: 50,
|
|
3604
|
+
min: 1,
|
|
3605
|
+
step: 1,
|
|
3606
|
+
type: "range",
|
|
3607
|
+
label: "Максимальное число шагов линейного увеличения размера",
|
|
3608
|
+
},
|
|
3609
|
+
{
|
|
3610
|
+
id: "nodeSizeLogFactor",
|
|
3611
|
+
initialValue: NODE_SETTINGS.nodeSizeLogFactor,
|
|
3612
|
+
max: 50,
|
|
3613
|
+
min: 1,
|
|
3614
|
+
step: 1,
|
|
3615
|
+
type: "range",
|
|
3616
|
+
label: "Число умножаемое на логарифм от количества связей для увеличения размера",
|
|
3617
|
+
},
|
|
3618
|
+
{
|
|
3619
|
+
id: "nodeSizeLinkCountDividerForLog",
|
|
3620
|
+
initialValue: NODE_SETTINGS.nodeSizeLinkCountDividerForLog,
|
|
3621
|
+
max: 50,
|
|
3622
|
+
min: 1,
|
|
3623
|
+
step: 1,
|
|
3519
3624
|
type: "range",
|
|
3520
|
-
label: "
|
|
3625
|
+
label: "Делитель количества связей для вычисления логарифма увеличения размера.",
|
|
3521
3626
|
},
|
|
3522
3627
|
{
|
|
3523
3628
|
id: "textScaleMin",
|
|
@@ -3581,7 +3686,6 @@ const NODE_OPTIONS_NODE_CONTROLS = [
|
|
|
3581
3686
|
initialValue: NODE_OPTIONS.shape,
|
|
3582
3687
|
label: "Форма",
|
|
3583
3688
|
options: [
|
|
3584
|
-
{ label: "Картинки", value: "icon" },
|
|
3585
3689
|
{ label: "Круг", value: "circle" },
|
|
3586
3690
|
{ label: "Прямоугольник", value: "square" },
|
|
3587
3691
|
{ label: "Текст", value: "text" },
|