@opendata-ai/openchart-vanilla 6.13.0 → 6.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +59 -22
- package/dist/index.js.map +1 -1
- package/dist/simulation-worker.js +38 -0
- package/dist/styles.css +1 -1
- package/package.json +3 -3
- package/src/graph/__tests__/canvas-renderer.test.ts +2 -2
- package/src/graph/__tests__/zoom.test.ts +5 -5
- package/src/graph/canvas-renderer.ts +0 -2
- package/src/graph/zoom.ts +24 -7
- package/src/graph-mount.ts +3 -5
- package/src/svg-renderer.ts +56 -8
package/dist/index.js
CHANGED
|
@@ -299,8 +299,6 @@ var GraphCanvasRenderer = class {
|
|
|
299
299
|
this.cssHeight = height;
|
|
300
300
|
this.canvas.width = width * this.dpr;
|
|
301
301
|
this.canvas.height = height * this.dpr;
|
|
302
|
-
this.canvas.style.width = `${width}px`;
|
|
303
|
-
this.canvas.style.height = `${height}px`;
|
|
304
302
|
}
|
|
305
303
|
/** Clear canvas and render the full graph state. */
|
|
306
304
|
render(state) {
|
|
@@ -796,20 +794,32 @@ var ZoomTransform = class _ZoomTransform {
|
|
|
796
794
|
if (n.x + r > maxX) maxX = n.x + r;
|
|
797
795
|
if (n.y + r > maxY) maxY = n.y + r;
|
|
798
796
|
}
|
|
799
|
-
|
|
800
|
-
|
|
797
|
+
let graphW = maxX - minX;
|
|
798
|
+
let graphH = maxY - minY;
|
|
801
799
|
if (graphW === 0 && graphH === 0) {
|
|
802
800
|
return {
|
|
803
801
|
transform: new _ZoomTransform(canvasW / 2 - minX, canvasH / 2 - minY, 1),
|
|
804
802
|
contentHeight: padding * 2
|
|
805
803
|
};
|
|
806
804
|
}
|
|
805
|
+
if (nodes.length > 50) {
|
|
806
|
+
const spread = 1 + Math.sqrt(nodes.length) / 120;
|
|
807
|
+
const cx2 = (minX + maxX) / 2;
|
|
808
|
+
const cy2 = (minY + maxY) / 2;
|
|
809
|
+
graphW *= spread;
|
|
810
|
+
graphH *= spread;
|
|
811
|
+
minX = cx2 - graphW / 2;
|
|
812
|
+
maxX = cx2 + graphW / 2;
|
|
813
|
+
minY = cy2 - graphH / 2;
|
|
814
|
+
maxY = cy2 + graphH / 2;
|
|
815
|
+
}
|
|
807
816
|
const availW = canvasW - padding * 2;
|
|
808
817
|
const availH = canvasH - padding * 2;
|
|
809
|
-
const k = Math.min(availW / graphW, availH / graphH);
|
|
818
|
+
const k = Math.min(1, availW / graphW, availH / graphH);
|
|
810
819
|
const cx = (minX + maxX) / 2;
|
|
820
|
+
const cy = (minY + maxY) / 2;
|
|
811
821
|
const tx = canvasW / 2 - cx * k;
|
|
812
|
-
const ty =
|
|
822
|
+
const ty = canvasH / 2 - cy * k;
|
|
813
823
|
const contentHeight = graphH * k + padding * 2;
|
|
814
824
|
return {
|
|
815
825
|
transform: new _ZoomTransform(tx, ty, k),
|
|
@@ -2811,8 +2821,7 @@ function createGraph(container, spec, options) {
|
|
|
2811
2821
|
wrapper.appendChild(legendEl);
|
|
2812
2822
|
}
|
|
2813
2823
|
container.appendChild(wrapper);
|
|
2814
|
-
const
|
|
2815
|
-
const canvasHeight = Math.max(height - chromeHeight, 200);
|
|
2824
|
+
const canvasHeight = Math.max(height, 200);
|
|
2816
2825
|
renderer = new GraphCanvasRenderer(canvas);
|
|
2817
2826
|
renderer.resize(width, canvasHeight);
|
|
2818
2827
|
}
|
|
@@ -3118,8 +3127,7 @@ function createGraph(container, spec, options) {
|
|
|
3118
3127
|
function doResize() {
|
|
3119
3128
|
if (destroyed || !canvas || !renderer || !wrapper) return;
|
|
3120
3129
|
const { width, height } = getContainerDimensions();
|
|
3121
|
-
const
|
|
3122
|
-
const canvasHeight = Math.max(height - chromeHeight, 200);
|
|
3130
|
+
const canvasHeight = Math.max(height, 200);
|
|
3123
3131
|
renderer.resize(width, canvasHeight);
|
|
3124
3132
|
needsRender = true;
|
|
3125
3133
|
scheduleRender();
|
|
@@ -3447,14 +3455,33 @@ function applyTextStyle(el, style) {
|
|
|
3447
3455
|
el.setAttribute("font-variant", style.fontVariant);
|
|
3448
3456
|
}
|
|
3449
3457
|
}
|
|
3450
|
-
function wrapText(text, fontSize, fontWeight, maxWidth) {
|
|
3458
|
+
function wrapText(text, fontSize, fontWeight, maxWidth, measureText) {
|
|
3451
3459
|
if (maxWidth <= 0) return [text];
|
|
3452
3460
|
const segments = text.split("\n");
|
|
3453
3461
|
if (segments.length > 1) {
|
|
3454
3462
|
return segments.flatMap(
|
|
3455
|
-
(segment) => segment.length === 0 ? [""] : wrapText(segment, fontSize, fontWeight, maxWidth)
|
|
3463
|
+
(segment) => segment.length === 0 ? [""] : wrapText(segment, fontSize, fontWeight, maxWidth, measureText)
|
|
3456
3464
|
);
|
|
3457
3465
|
}
|
|
3466
|
+
if (measureText) {
|
|
3467
|
+
const textWidth = measureText(text, fontSize, fontWeight).width;
|
|
3468
|
+
if (textWidth <= maxWidth) return [text];
|
|
3469
|
+
const words2 = text.split(" ");
|
|
3470
|
+
const lines2 = [];
|
|
3471
|
+
let current2 = "";
|
|
3472
|
+
for (const word of words2) {
|
|
3473
|
+
const candidate = current2 ? `${current2} ${word}` : word;
|
|
3474
|
+
const candidateWidth = measureText(candidate, fontSize, fontWeight).width;
|
|
3475
|
+
if (candidateWidth > maxWidth && current2) {
|
|
3476
|
+
lines2.push(current2);
|
|
3477
|
+
current2 = word;
|
|
3478
|
+
} else {
|
|
3479
|
+
current2 = candidate;
|
|
3480
|
+
}
|
|
3481
|
+
}
|
|
3482
|
+
if (current2) lines2.push(current2);
|
|
3483
|
+
return lines2;
|
|
3484
|
+
}
|
|
3458
3485
|
const AVG_CHAR_WIDTH = 0.55;
|
|
3459
3486
|
const WEIGHT_FACTORS = {
|
|
3460
3487
|
100: 0.9,
|
|
@@ -3486,7 +3513,7 @@ function wrapText(text, fontSize, fontWeight, maxWidth) {
|
|
|
3486
3513
|
if (current) lines.push(current);
|
|
3487
3514
|
return lines;
|
|
3488
3515
|
}
|
|
3489
|
-
function renderChromeElement(parent, element, className, chromeKey) {
|
|
3516
|
+
function renderChromeElement(parent, element, className, chromeKey, measureText) {
|
|
3490
3517
|
const text = createSVGElement("text");
|
|
3491
3518
|
setAttrs(text, { x: element.x, y: element.y });
|
|
3492
3519
|
applyTextStyle(text, element.style);
|
|
@@ -3496,7 +3523,8 @@ function renderChromeElement(parent, element, className, chromeKey) {
|
|
|
3496
3523
|
element.text,
|
|
3497
3524
|
element.style.fontSize,
|
|
3498
3525
|
element.style.fontWeight,
|
|
3499
|
-
element.maxWidth
|
|
3526
|
+
element.maxWidth,
|
|
3527
|
+
measureText
|
|
3500
3528
|
);
|
|
3501
3529
|
if (lines.length === 1) {
|
|
3502
3530
|
text.textContent = element.text;
|
|
@@ -3514,12 +3542,12 @@ function renderChromeElement(parent, element, className, chromeKey) {
|
|
|
3514
3542
|
function renderChrome(parent, layout) {
|
|
3515
3543
|
const g = createSVGElement("g");
|
|
3516
3544
|
g.setAttribute("class", "oc-chrome");
|
|
3517
|
-
const { chrome } = layout;
|
|
3545
|
+
const { chrome, measureText } = layout;
|
|
3518
3546
|
if (chrome.title) {
|
|
3519
|
-
renderChromeElement(g, chrome.title, "oc-title", "title");
|
|
3547
|
+
renderChromeElement(g, chrome.title, "oc-title", "title", measureText);
|
|
3520
3548
|
}
|
|
3521
3549
|
if (chrome.subtitle) {
|
|
3522
|
-
renderChromeElement(g, chrome.subtitle, "oc-subtitle", "subtitle");
|
|
3550
|
+
renderChromeElement(g, chrome.subtitle, "oc-subtitle", "subtitle", measureText);
|
|
3523
3551
|
}
|
|
3524
3552
|
const xAxisExtent = computeXAxisExtent(layout);
|
|
3525
3553
|
const bottomOffset = layout.area.y + layout.area.height + xAxisExtent;
|
|
@@ -3528,7 +3556,8 @@ function renderChrome(parent, layout) {
|
|
|
3528
3556
|
g,
|
|
3529
3557
|
{ ...chrome.source, y: bottomOffset + chrome.source.y },
|
|
3530
3558
|
"oc-source",
|
|
3531
|
-
"source"
|
|
3559
|
+
"source",
|
|
3560
|
+
measureText
|
|
3532
3561
|
);
|
|
3533
3562
|
}
|
|
3534
3563
|
if (chrome.byline) {
|
|
@@ -3536,7 +3565,8 @@ function renderChrome(parent, layout) {
|
|
|
3536
3565
|
g,
|
|
3537
3566
|
{ ...chrome.byline, y: bottomOffset + chrome.byline.y },
|
|
3538
3567
|
"oc-byline",
|
|
3539
|
-
"byline"
|
|
3568
|
+
"byline",
|
|
3569
|
+
measureText
|
|
3540
3570
|
);
|
|
3541
3571
|
}
|
|
3542
3572
|
if (chrome.footer) {
|
|
@@ -3544,7 +3574,8 @@ function renderChrome(parent, layout) {
|
|
|
3544
3574
|
g,
|
|
3545
3575
|
{ ...chrome.footer, y: bottomOffset + chrome.footer.y },
|
|
3546
3576
|
"oc-footer",
|
|
3547
|
-
"footer"
|
|
3577
|
+
"footer",
|
|
3578
|
+
measureText
|
|
3548
3579
|
);
|
|
3549
3580
|
}
|
|
3550
3581
|
parent.appendChild(g);
|
|
@@ -3967,8 +3998,9 @@ function renderAnnotations(parent, layout) {
|
|
|
3967
3998
|
if (layout.annotations.length === 0) return;
|
|
3968
3999
|
const g = createSVGElement("g");
|
|
3969
4000
|
g.setAttribute("class", "oc-annotations");
|
|
4001
|
+
const bgColor = layout.theme.colors.background;
|
|
3970
4002
|
for (let i = 0; i < layout.annotations.length; i++) {
|
|
3971
|
-
renderAnnotation(g, layout.annotations[i], i);
|
|
4003
|
+
renderAnnotation(g, layout.annotations[i], i, bgColor);
|
|
3972
4004
|
}
|
|
3973
4005
|
parent.appendChild(g);
|
|
3974
4006
|
}
|
|
@@ -4014,7 +4046,7 @@ function renderCurvedArrow(parent, from, to, stroke) {
|
|
|
4014
4046
|
});
|
|
4015
4047
|
parent.appendChild(arrow);
|
|
4016
4048
|
}
|
|
4017
|
-
function renderAnnotation(parent, annotation, index2) {
|
|
4049
|
+
function renderAnnotation(parent, annotation, index2, bgColor) {
|
|
4018
4050
|
const g = createSVGElement("g");
|
|
4019
4051
|
g.setAttribute("class", `oc-annotation oc-annotation-${annotation.type}`);
|
|
4020
4052
|
g.setAttribute("data-annotation-index", String(index2));
|
|
@@ -4108,6 +4140,11 @@ function renderAnnotation(parent, annotation, index2) {
|
|
|
4108
4140
|
rx: 2
|
|
4109
4141
|
});
|
|
4110
4142
|
g.appendChild(bgRect);
|
|
4143
|
+
} else if (bgColor) {
|
|
4144
|
+
text.style.paintOrder = "stroke";
|
|
4145
|
+
text.style.stroke = bgColor;
|
|
4146
|
+
text.style.strokeWidth = `${Math.round(fontSize * 0.3)}px`;
|
|
4147
|
+
text.style.strokeLinejoin = "round";
|
|
4111
4148
|
}
|
|
4112
4149
|
g.appendChild(text);
|
|
4113
4150
|
}
|