@visactor/vrender-components 0.14.0-alpha.8 → 0.14.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/cjs/axis/base.d.ts +4 -2
- package/cjs/axis/base.js +11 -20
- package/cjs/axis/base.js.map +1 -1
- package/cjs/axis/circle.d.ts +3 -1
- package/cjs/axis/circle.js +7 -5
- package/cjs/axis/circle.js.map +1 -1
- package/cjs/axis/constant.d.ts +2 -1
- package/cjs/axis/constant.js +1 -1
- package/cjs/axis/constant.js.map +1 -1
- package/cjs/axis/line.d.ts +6 -2
- package/cjs/axis/line.js +71 -14
- package/cjs/axis/line.js.map +1 -1
- package/cjs/axis/overlap/auto-limit.js +6 -2
- package/cjs/axis/overlap/auto-limit.js.map +1 -1
- package/cjs/axis/overlap/auto-rotate.d.ts +2 -0
- package/cjs/axis/overlap/auto-rotate.js +2 -2
- package/cjs/axis/overlap/auto-rotate.js.map +1 -1
- package/cjs/axis/type.d.ts +13 -9
- package/cjs/axis/type.js.map +1 -1
- package/cjs/brush/brush.d.ts +1 -0
- package/cjs/brush/brush.js +27 -17
- package/cjs/brush/brush.js.map +1 -1
- package/cjs/brush/config.d.ts +1 -0
- package/cjs/brush/config.js +3 -2
- package/cjs/brush/config.js.map +1 -1
- package/cjs/brush/type.d.ts +11 -1
- package/cjs/brush/type.js +7 -1
- package/cjs/brush/type.js.map +1 -1
- package/cjs/index.d.ts +1 -1
- package/cjs/index.js +1 -1
- package/cjs/index.js.map +1 -1
- package/cjs/label/arc.d.ts +71 -0
- package/cjs/label/arc.js +409 -0
- package/cjs/label/arc.js.map +1 -0
- package/cjs/label/base.d.ts +1 -0
- package/cjs/label/base.js +51 -7
- package/cjs/label/base.js.map +1 -1
- package/cjs/label/dataLabel.js +3 -2
- package/cjs/label/dataLabel.js.map +1 -1
- package/cjs/label/index.d.ts +1 -0
- package/cjs/label/index.js +2 -1
- package/cjs/label/index.js.map +1 -1
- package/cjs/label/overlap/bitmap.d.ts +1 -1
- package/cjs/label/overlap/bitmap.js +2 -0
- package/cjs/label/overlap/bitmap.js.map +1 -1
- package/cjs/label/type.d.ts +43 -2
- package/cjs/label/type.js.map +1 -1
- package/cjs/label/util.d.ts +12 -0
- package/cjs/label/util.js +113 -0
- package/cjs/label/util.js.map +1 -0
- package/cjs/link-path/type.js +1 -2
- package/cjs/marker/base.js +2 -1
- package/cjs/pager/index.js +1 -1
- package/cjs/pager/pager.js +1 -1
- package/cjs/util/align.d.ts +2 -0
- package/cjs/util/align.js +60 -0
- package/cjs/util/align.js.map +1 -0
- package/dist/index.js +1103 -81
- package/dist/index.min.js +1 -1
- package/es/axis/base.d.ts +4 -2
- package/es/axis/base.js +12 -21
- package/es/axis/base.js.map +1 -1
- package/es/axis/circle.d.ts +3 -1
- package/es/axis/circle.js +7 -5
- package/es/axis/circle.js.map +1 -1
- package/es/axis/constant.d.ts +2 -1
- package/es/axis/constant.js +1 -1
- package/es/axis/constant.js.map +1 -1
- package/es/axis/line.d.ts +6 -2
- package/es/axis/line.js +74 -15
- package/es/axis/line.js.map +1 -1
- package/es/axis/overlap/auto-limit.js +5 -2
- package/es/axis/overlap/auto-limit.js.map +1 -1
- package/es/axis/overlap/auto-rotate.d.ts +2 -0
- package/es/axis/overlap/auto-rotate.js +2 -2
- package/es/axis/overlap/auto-rotate.js.map +1 -1
- package/es/axis/type.d.ts +13 -9
- package/es/axis/type.js.map +1 -1
- package/es/brush/brush.d.ts +1 -0
- package/es/brush/brush.js +27 -15
- package/es/brush/brush.js.map +1 -1
- package/es/brush/config.d.ts +1 -0
- package/es/brush/config.js +2 -0
- package/es/brush/config.js.map +1 -1
- package/es/brush/type.d.ts +11 -1
- package/es/brush/type.js +7 -1
- package/es/brush/type.js.map +1 -1
- package/es/index.d.ts +1 -1
- package/es/index.js +1 -1
- package/es/index.js.map +1 -1
- package/es/label/arc.d.ts +71 -0
- package/es/label/arc.js +398 -0
- package/es/label/arc.js.map +1 -0
- package/es/label/base.d.ts +1 -0
- package/es/label/base.js +51 -8
- package/es/label/base.js.map +1 -1
- package/es/label/dataLabel.js +4 -1
- package/es/label/dataLabel.js.map +1 -1
- package/es/label/index.d.ts +1 -0
- package/es/label/index.js +2 -0
- package/es/label/index.js.map +1 -1
- package/es/label/overlap/bitmap.d.ts +1 -1
- package/es/label/overlap/bitmap.js +2 -0
- package/es/label/overlap/bitmap.js.map +1 -1
- package/es/label/type.d.ts +43 -2
- package/es/label/type.js.map +1 -1
- package/es/label/util.d.ts +12 -0
- package/es/label/util.js +99 -0
- package/es/label/util.js.map +1 -0
- package/es/link-path/type.js +1 -2
- package/es/marker/base.js +2 -1
- package/es/pager/index.js +1 -1
- package/es/pager/pager.js +1 -1
- package/es/util/align.d.ts +2 -0
- package/es/util/align.js +54 -0
- package/es/util/align.js.map +1 -0
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1331,6 +1331,9 @@
|
|
|
1331
1331
|
_clear(index >>> DIV, ~(1 << (index & MOD)));
|
|
1332
1332
|
},
|
|
1333
1333
|
getRange: ({ x1, y1, x2, y2 }) => {
|
|
1334
|
+
if (x2 < 0 || y2 < 0 || x1 > w || y1 > h) {
|
|
1335
|
+
return true;
|
|
1336
|
+
}
|
|
1334
1337
|
let r = y2;
|
|
1335
1338
|
let start;
|
|
1336
1339
|
let end;
|
|
@@ -1363,6 +1366,9 @@
|
|
|
1363
1366
|
return false;
|
|
1364
1367
|
},
|
|
1365
1368
|
setRange: ({ x1, y1, x2, y2 }) => {
|
|
1369
|
+
if (x2 < 0 || y2 < 0 || x1 > w || y1 > h) {
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1366
1372
|
let start;
|
|
1367
1373
|
let end;
|
|
1368
1374
|
let indexStart;
|
|
@@ -1612,6 +1618,10 @@
|
|
|
1612
1618
|
_lastHover;
|
|
1613
1619
|
_lastSelect;
|
|
1614
1620
|
_enableAnimation;
|
|
1621
|
+
layoutArcLabels(position, attribute, currentMarks, data, textBoundsArray) {
|
|
1622
|
+
const arcs = [];
|
|
1623
|
+
return arcs;
|
|
1624
|
+
}
|
|
1615
1625
|
render() {
|
|
1616
1626
|
this._prepare();
|
|
1617
1627
|
const { overlap, smartInvert, dataFilter, customLayoutFunc, customOverlapFunc } = this.attribute;
|
|
@@ -1747,15 +1757,18 @@
|
|
|
1747
1757
|
layout(data = []) {
|
|
1748
1758
|
const { textStyle = {}, position, offset } = this.attribute;
|
|
1749
1759
|
const labels = [];
|
|
1760
|
+
const textBoundsArray = [];
|
|
1750
1761
|
for (let i = 0; i < data.length; i++) {
|
|
1751
1762
|
const textData = data[i];
|
|
1752
1763
|
const baseMark = this._idToGraphic.get(textData.id);
|
|
1753
1764
|
const labelAttribute = {
|
|
1765
|
+
fill: baseMark.attribute.fill,
|
|
1754
1766
|
...textStyle,
|
|
1755
1767
|
...textData
|
|
1756
1768
|
};
|
|
1757
1769
|
const text = this._createLabelText(labelAttribute);
|
|
1758
1770
|
const textBounds = this.getGraphicBounds(text);
|
|
1771
|
+
textBoundsArray.push(textBounds);
|
|
1759
1772
|
const graphicBounds = this.getGraphicBounds(baseMark, { x: textData.x, y: textData.y });
|
|
1760
1773
|
const textLocation = this.labeling(textBounds, graphicBounds, vutils.isFunction(position) ? position(textData) : position, offset);
|
|
1761
1774
|
if (!textLocation) {
|
|
@@ -1766,6 +1779,20 @@
|
|
|
1766
1779
|
text.setAttributes(textLocation);
|
|
1767
1780
|
labels.push(text);
|
|
1768
1781
|
}
|
|
1782
|
+
if (this.attribute.type === 'arc') {
|
|
1783
|
+
const arcs = this.layoutArcLabels(position, this.attribute, Array.from(this._idToGraphic.values()), data, textBoundsArray);
|
|
1784
|
+
for (let i = 0; i < data.length; i++) {
|
|
1785
|
+
const textData = data[i];
|
|
1786
|
+
const basedArc = arcs.find(arc => arc.labelText === textData.text);
|
|
1787
|
+
const labelAttribute = {
|
|
1788
|
+
x: basedArc.labelPosition.x,
|
|
1789
|
+
y: basedArc.labelPosition.y,
|
|
1790
|
+
angle: this.attribute.angle ?? basedArc.angle,
|
|
1791
|
+
labelLinePath: basedArc.labelLinePath
|
|
1792
|
+
};
|
|
1793
|
+
labels[i].setAttributes(labelAttribute);
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1769
1796
|
return labels;
|
|
1770
1797
|
}
|
|
1771
1798
|
_overlapping(labels) {
|
|
@@ -1822,6 +1849,20 @@
|
|
|
1822
1849
|
continue;
|
|
1823
1850
|
}
|
|
1824
1851
|
}
|
|
1852
|
+
if (clampForce) {
|
|
1853
|
+
const { dx = 0, dy = 0 } = clampText(text, bmpTool.width, bmpTool.height);
|
|
1854
|
+
if (!(dx === 0 && dy === 0) &&
|
|
1855
|
+
canPlace(bmpTool, bitmap, {
|
|
1856
|
+
x1: text.AABBBounds.x1 + dx,
|
|
1857
|
+
x2: text.AABBBounds.x2 + dx,
|
|
1858
|
+
y1: text.AABBBounds.y1 + dy,
|
|
1859
|
+
y2: text.AABBBounds.y2 + dy
|
|
1860
|
+
})) {
|
|
1861
|
+
text.setAttributes({ x: text.attribute.x + dx, y: text.attribute.y + dy });
|
|
1862
|
+
result.push(text);
|
|
1863
|
+
continue;
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1825
1866
|
let hasPlace = false;
|
|
1826
1867
|
for (let j = 0; j < strategy.length; j++) {
|
|
1827
1868
|
hasPlace = place(bmpTool, bitmap, strategy[j], this.attribute, text, this.getGraphicBounds(baseMark, labels[i]), this.labeling);
|
|
@@ -1880,6 +1921,14 @@
|
|
|
1880
1921
|
const prevTextMap = this._graphicToText || new Map();
|
|
1881
1922
|
const texts = [];
|
|
1882
1923
|
labels.forEach((text, index) => {
|
|
1924
|
+
const labelLine = text.attribute?.labelLinePath
|
|
1925
|
+
? vrender.createPath({
|
|
1926
|
+
visible: text.attribute?.visible ?? true,
|
|
1927
|
+
stroke: text.attribute?.line?.stroke ?? text.attribute?.fill,
|
|
1928
|
+
lineWidth: 1,
|
|
1929
|
+
path: text.attribute?.labelLinePath
|
|
1930
|
+
})
|
|
1931
|
+
: undefined;
|
|
1883
1932
|
const relatedGraphic = this._idToGraphic.get(text.attribute.id);
|
|
1884
1933
|
const state = prevTextMap?.get(relatedGraphic) ? 'update' : 'enter';
|
|
1885
1934
|
if (state === 'enter') {
|
|
@@ -1888,6 +1937,9 @@
|
|
|
1888
1937
|
if (!disableAnimation && relatedGraphic) {
|
|
1889
1938
|
const { from, to } = getAnimationAttributes(text.attribute, 'fadeIn');
|
|
1890
1939
|
this.add(text);
|
|
1940
|
+
if (labelLine) {
|
|
1941
|
+
this.add(labelLine);
|
|
1942
|
+
}
|
|
1891
1943
|
relatedGraphic.onAnimateBind = () => {
|
|
1892
1944
|
text.setAttributes(from);
|
|
1893
1945
|
const listener = this._afterRelatedGraphicAttributeUpdate(text, texts, index, relatedGraphic, {
|
|
@@ -1902,6 +1954,9 @@
|
|
|
1902
1954
|
}
|
|
1903
1955
|
else {
|
|
1904
1956
|
this.add(text);
|
|
1957
|
+
if (labelLine) {
|
|
1958
|
+
this.add(labelLine);
|
|
1959
|
+
}
|
|
1905
1960
|
}
|
|
1906
1961
|
}
|
|
1907
1962
|
if (state === 'update') {
|
|
@@ -1995,7 +2050,15 @@
|
|
|
1995
2050
|
continue;
|
|
1996
2051
|
}
|
|
1997
2052
|
const baseMark = this._idToGraphic.get(label.attribute.id);
|
|
1998
|
-
|
|
2053
|
+
let isInside = canPlaceInside(label.AABBBounds, baseMark?.AABBBounds);
|
|
2054
|
+
if (this.attribute.type === 'arc') {
|
|
2055
|
+
if (this.attribute.position === 'inside') {
|
|
2056
|
+
isInside = true;
|
|
2057
|
+
}
|
|
2058
|
+
else {
|
|
2059
|
+
isInside = false;
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
1999
2062
|
if (label.attribute.stroke && label.attribute.lineWidth > 0) {
|
|
2000
2063
|
label.setAttributes({
|
|
2001
2064
|
fill: labelSmartInvert(label.attribute.fill, label.attribute.stroke, textType, contrastRatiosThreshold, alternativeColors)
|
|
@@ -2222,9 +2285,785 @@
|
|
|
2222
2285
|
}
|
|
2223
2286
|
}
|
|
2224
2287
|
|
|
2288
|
+
function polarToCartesian(point) {
|
|
2289
|
+
if (!point.radius) {
|
|
2290
|
+
return { x: 0, y: 0 };
|
|
2291
|
+
}
|
|
2292
|
+
return {
|
|
2293
|
+
x: Math.cos(point.angle) * point.radius,
|
|
2294
|
+
y: Math.sin(point.angle) * point.radius
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
function circlePoint(x0, y0, radius, radian) {
|
|
2298
|
+
const offset = polarToCartesian({
|
|
2299
|
+
radius,
|
|
2300
|
+
angle: radian
|
|
2301
|
+
});
|
|
2302
|
+
return {
|
|
2303
|
+
x: x0 + offset.x,
|
|
2304
|
+
y: y0 + offset.y
|
|
2305
|
+
};
|
|
2306
|
+
}
|
|
2307
|
+
function computeQuadrant(angle) {
|
|
2308
|
+
angle = normalizeAngle(angle);
|
|
2309
|
+
if (angle > 0 && angle <= Math.PI / 2) {
|
|
2310
|
+
return 2;
|
|
2311
|
+
}
|
|
2312
|
+
else if (angle > Math.PI / 2 && angle <= Math.PI) {
|
|
2313
|
+
return 3;
|
|
2314
|
+
}
|
|
2315
|
+
else if (angle > Math.PI && angle <= (3 * Math.PI) / 2) {
|
|
2316
|
+
return 4;
|
|
2317
|
+
}
|
|
2318
|
+
return 1;
|
|
2319
|
+
}
|
|
2320
|
+
function normalizeAngle(angle) {
|
|
2321
|
+
while (angle < 0) {
|
|
2322
|
+
angle += Math.PI * 2;
|
|
2323
|
+
}
|
|
2324
|
+
while (angle >= Math.PI * 2) {
|
|
2325
|
+
angle -= Math.PI * 2;
|
|
2326
|
+
}
|
|
2327
|
+
return angle;
|
|
2328
|
+
}
|
|
2329
|
+
function isQuadrantLeft(quadrant) {
|
|
2330
|
+
return quadrant === 3 || quadrant === 4;
|
|
2331
|
+
}
|
|
2332
|
+
function isQuadrantRight(quadrant) {
|
|
2333
|
+
return quadrant === 1 || quadrant === 2;
|
|
2334
|
+
}
|
|
2335
|
+
function lineCirclePoints(a, b, c, x0, y0, r) {
|
|
2336
|
+
if ((a === 0 && b === 0) || r <= 0) {
|
|
2337
|
+
return [];
|
|
2338
|
+
}
|
|
2339
|
+
if (a === 0) {
|
|
2340
|
+
const y1 = -c / b;
|
|
2341
|
+
const fy = (y1 - y0) ** 2;
|
|
2342
|
+
const fd = r ** 2 - fy;
|
|
2343
|
+
if (fd < 0) {
|
|
2344
|
+
return [];
|
|
2345
|
+
}
|
|
2346
|
+
else if (fd === 0) {
|
|
2347
|
+
return [{ x: x0, y: y1 }];
|
|
2348
|
+
}
|
|
2349
|
+
const x1 = Math.sqrt(fd) + x0;
|
|
2350
|
+
const x2 = -Math.sqrt(fd) + x0;
|
|
2351
|
+
return [
|
|
2352
|
+
{ x: x1, y: y1 },
|
|
2353
|
+
{ x: x2, y: y1 }
|
|
2354
|
+
];
|
|
2355
|
+
}
|
|
2356
|
+
else if (b === 0) {
|
|
2357
|
+
const x1 = -c / a;
|
|
2358
|
+
const fx = (x1 - x0) ** 2;
|
|
2359
|
+
const fd = r ** 2 - fx;
|
|
2360
|
+
if (fd < 0) {
|
|
2361
|
+
return [];
|
|
2362
|
+
}
|
|
2363
|
+
else if (fd === 0) {
|
|
2364
|
+
return [{ x: x1, y: y0 }];
|
|
2365
|
+
}
|
|
2366
|
+
const y1 = Math.sqrt(fd) + y0;
|
|
2367
|
+
const y2 = -Math.sqrt(fd) + y0;
|
|
2368
|
+
return [
|
|
2369
|
+
{ x: x1, y: y1 },
|
|
2370
|
+
{ x: x1, y: y2 }
|
|
2371
|
+
];
|
|
2372
|
+
}
|
|
2373
|
+
const fa = (b / a) ** 2 + 1;
|
|
2374
|
+
const fb = 2 * ((c / a + x0) * (b / a) - y0);
|
|
2375
|
+
const fc = (c / a + x0) ** 2 + y0 ** 2 - r ** 2;
|
|
2376
|
+
const fd = fb ** 2 - 4 * fa * fc;
|
|
2377
|
+
if (fd < 0) {
|
|
2378
|
+
return [];
|
|
2379
|
+
}
|
|
2380
|
+
const y1 = (-fb + Math.sqrt(fd)) / (2 * fa);
|
|
2381
|
+
const y2 = (-fb - Math.sqrt(fd)) / (2 * fa);
|
|
2382
|
+
const x1 = -(b * y1 + c) / a;
|
|
2383
|
+
const x2 = -(b * y2 + c) / a;
|
|
2384
|
+
if (fd === 0) {
|
|
2385
|
+
return [{ x: x1, y: y1 }];
|
|
2386
|
+
}
|
|
2387
|
+
return [
|
|
2388
|
+
{ x: x1, y: y1 },
|
|
2389
|
+
{ x: x2, y: y2 }
|
|
2390
|
+
];
|
|
2391
|
+
}
|
|
2392
|
+
function connectLineRadian(radius, length) {
|
|
2393
|
+
if (length > radius * 2) {
|
|
2394
|
+
return NaN;
|
|
2395
|
+
}
|
|
2396
|
+
return Math.asin(length / 2 / radius) * 2;
|
|
2397
|
+
}
|
|
2398
|
+
function checkBoundsOverlap(boundsA, boundsB) {
|
|
2399
|
+
const { x1: ax1, y1: ay1, x2: ax2, y2: ay2 } = boundsA;
|
|
2400
|
+
const { x1: bx1, y1: by1, x2: bx2, y2: by2 } = boundsB;
|
|
2401
|
+
return !((ax1 <= bx1 && ax2 <= bx1) ||
|
|
2402
|
+
(ax1 >= bx2 && ax2 >= bx2) ||
|
|
2403
|
+
(ay1 <= by1 && ay2 <= by1) ||
|
|
2404
|
+
(ay1 >= by2 && ay2 >= by2));
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2407
|
+
class ArcInfo {
|
|
2408
|
+
key;
|
|
2409
|
+
refDatum;
|
|
2410
|
+
center;
|
|
2411
|
+
outerCenter;
|
|
2412
|
+
labelSize;
|
|
2413
|
+
labelPosition;
|
|
2414
|
+
labelLimit;
|
|
2415
|
+
labelVisible;
|
|
2416
|
+
lastLabelY;
|
|
2417
|
+
labelYRange;
|
|
2418
|
+
labelText;
|
|
2419
|
+
pointA;
|
|
2420
|
+
pointB;
|
|
2421
|
+
pointC;
|
|
2422
|
+
labelLinePath;
|
|
2423
|
+
quadrant;
|
|
2424
|
+
radian;
|
|
2425
|
+
middleAngle;
|
|
2426
|
+
k;
|
|
2427
|
+
textAlign;
|
|
2428
|
+
textBaseline;
|
|
2429
|
+
angle;
|
|
2430
|
+
constructor(refDatum, center, outerCenter, quadrant, radian, middleAngle) {
|
|
2431
|
+
this.refDatum = refDatum;
|
|
2432
|
+
this.center = center;
|
|
2433
|
+
this.outerCenter = outerCenter;
|
|
2434
|
+
this.quadrant = quadrant;
|
|
2435
|
+
this.radian = radian;
|
|
2436
|
+
this.middleAngle = middleAngle;
|
|
2437
|
+
this.labelVisible = true;
|
|
2438
|
+
this.labelLimit = 0;
|
|
2439
|
+
}
|
|
2440
|
+
getLabelBounds() {
|
|
2441
|
+
if (!this.labelPosition || !this.labelSize) {
|
|
2442
|
+
return { x1: 0, x2: 0, y1: 0, y2: 0 };
|
|
2443
|
+
}
|
|
2444
|
+
return {
|
|
2445
|
+
x1: this.labelPosition.x - this.labelSize.width / 2,
|
|
2446
|
+
y1: this.labelPosition.y - this.labelSize.height / 2,
|
|
2447
|
+
x2: this.labelPosition.x + this.labelSize.width / 2,
|
|
2448
|
+
y2: this.labelPosition.y + this.labelSize.height / 2
|
|
2449
|
+
};
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
class ArcLabel extends LabelBase {
|
|
2453
|
+
name = 'arc-label';
|
|
2454
|
+
static defaultAttributes = {
|
|
2455
|
+
coverEnable: false,
|
|
2456
|
+
spaceWidth: 5,
|
|
2457
|
+
layoutArcGap: 6,
|
|
2458
|
+
textStyle: {
|
|
2459
|
+
visible: true,
|
|
2460
|
+
fontSize: 14,
|
|
2461
|
+
fontWeight: 'normal',
|
|
2462
|
+
fillOpacity: 1,
|
|
2463
|
+
textAlign: 'center',
|
|
2464
|
+
textBaseline: 'middle'
|
|
2465
|
+
},
|
|
2466
|
+
position: 'outside',
|
|
2467
|
+
offset: 0,
|
|
2468
|
+
line: {
|
|
2469
|
+
visible: true,
|
|
2470
|
+
line1MinLength: 20,
|
|
2471
|
+
line2MinLength: 10
|
|
2472
|
+
},
|
|
2473
|
+
layout: {
|
|
2474
|
+
align: 'arc',
|
|
2475
|
+
strategy: 'priority',
|
|
2476
|
+
tangentConstraint: true
|
|
2477
|
+
}
|
|
2478
|
+
};
|
|
2479
|
+
_ellipsisWidth = 0;
|
|
2480
|
+
_arcLeft = new Map();
|
|
2481
|
+
_arcRight = new Map();
|
|
2482
|
+
constructor(attributes) {
|
|
2483
|
+
super(vutils.merge({}, ArcLabel.defaultAttributes, attributes));
|
|
2484
|
+
}
|
|
2485
|
+
_overlapping(labels) {
|
|
2486
|
+
return labels;
|
|
2487
|
+
}
|
|
2488
|
+
labeling(textBounds, graphicBounds, position = 'outside', offset = 0) {
|
|
2489
|
+
if (!textBounds || !graphicBounds) {
|
|
2490
|
+
return;
|
|
2491
|
+
}
|
|
2492
|
+
return { x: 0, y: 0 };
|
|
2493
|
+
}
|
|
2494
|
+
layoutArcLabels(position, attribute, currentMarks, data, textBoundsArray) {
|
|
2495
|
+
this._arcLeft.clear();
|
|
2496
|
+
this._arcRight.clear();
|
|
2497
|
+
const { width, height } = attribute;
|
|
2498
|
+
currentMarks.forEach((currentMark, index) => {
|
|
2499
|
+
const graphicAttribute = currentMark.attribute;
|
|
2500
|
+
const radiusRatio = this.computeLayoutOuterRadius(graphicAttribute.outerRadius, width, height);
|
|
2501
|
+
const radius = this.computeRadius(radiusRatio, width, height);
|
|
2502
|
+
const center = { x: graphicAttribute?.x ?? 0, y: graphicAttribute?.y ?? 0 };
|
|
2503
|
+
const item = data[index];
|
|
2504
|
+
const textBounds = textBoundsArray[index];
|
|
2505
|
+
const arcMiddleAngle = (graphicAttribute.startAngle + graphicAttribute.endAngle) / 2;
|
|
2506
|
+
const intervalAngle = graphicAttribute.endAngle - graphicAttribute.startAngle;
|
|
2507
|
+
const arcQuadrant = computeQuadrant(graphicAttribute.endAngle - intervalAngle / 2);
|
|
2508
|
+
const arcMiddle = circlePoint(center.x, center.y, graphicAttribute.outerRadius, arcMiddleAngle);
|
|
2509
|
+
const outerArcMiddle = circlePoint(center.x, center.y, radius + attribute.line.line1MinLength, arcMiddleAngle);
|
|
2510
|
+
const arc = new ArcInfo(item, arcMiddle, outerArcMiddle, arcQuadrant, intervalAngle, arcMiddleAngle);
|
|
2511
|
+
arc.pointA = circlePoint(center.x, center.y, this.computeDatumRadius(center.x * 2, center.y * 2, graphicAttribute.outerRadius), arc.middleAngle);
|
|
2512
|
+
arc.labelSize = {
|
|
2513
|
+
width: textBounds.x2 - textBounds.x1,
|
|
2514
|
+
height: textBounds.y2 - textBounds.y1
|
|
2515
|
+
};
|
|
2516
|
+
if (isQuadrantRight(arc.quadrant)) {
|
|
2517
|
+
this._arcRight.set(arc.refDatum, arc);
|
|
2518
|
+
}
|
|
2519
|
+
else if (isQuadrantLeft(arc.quadrant)) {
|
|
2520
|
+
this._arcLeft.set(arc.refDatum, arc);
|
|
2521
|
+
}
|
|
2522
|
+
});
|
|
2523
|
+
const leftArcs = Array.from(this._arcLeft.values());
|
|
2524
|
+
const rightArcs = Array.from(this._arcRight.values());
|
|
2525
|
+
const arcs = [];
|
|
2526
|
+
if (position === 'inside') {
|
|
2527
|
+
arcs.push(...this._layoutInsideLabels(rightArcs, attribute, currentMarks));
|
|
2528
|
+
arcs.push(...this._layoutInsideLabels(leftArcs, attribute, currentMarks));
|
|
2529
|
+
}
|
|
2530
|
+
else {
|
|
2531
|
+
arcs.push(...this._layoutOutsideLabels(rightArcs, attribute, currentMarks));
|
|
2532
|
+
arcs.push(...this._layoutOutsideLabels(leftArcs, attribute, currentMarks));
|
|
2533
|
+
}
|
|
2534
|
+
return arcs;
|
|
2535
|
+
}
|
|
2536
|
+
_layoutInsideLabels(arcs, attribute, currentMarks) {
|
|
2537
|
+
const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
|
|
2538
|
+
const innerRadiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.innerRadius, attribute.width, attribute.height);
|
|
2539
|
+
const outerRadiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
|
|
2540
|
+
const labelConfig = attribute;
|
|
2541
|
+
const spaceWidth = labelConfig.spaceWidth;
|
|
2542
|
+
arcs.forEach((arc) => {
|
|
2543
|
+
const { labelSize, radian } = arc;
|
|
2544
|
+
const innerRadius = this.computeRadius(innerRadiusRatio, attribute.width, attribute.height, 1);
|
|
2545
|
+
const outerRadius = this.computeRadius(outerRadiusRatio, attribute.width, attribute.height, 1);
|
|
2546
|
+
const minRadian = connectLineRadian(outerRadius, labelSize.height);
|
|
2547
|
+
let limit;
|
|
2548
|
+
if (radian < minRadian) {
|
|
2549
|
+
limit = 0;
|
|
2550
|
+
}
|
|
2551
|
+
else {
|
|
2552
|
+
let minRadius;
|
|
2553
|
+
if (radian >= Math.PI) {
|
|
2554
|
+
minRadius = innerRadius;
|
|
2555
|
+
}
|
|
2556
|
+
else {
|
|
2557
|
+
minRadius = Math.max(innerRadius, labelSize.height / 2 / Math.tan(radian / 2));
|
|
2558
|
+
}
|
|
2559
|
+
limit = outerRadius - minRadius - spaceWidth;
|
|
2560
|
+
}
|
|
2561
|
+
if (labelConfig?.rotate !== true) {
|
|
2562
|
+
limit = outerRadius - spaceWidth;
|
|
2563
|
+
}
|
|
2564
|
+
const text = this._getFormatLabelText(arc.refDatum, limit);
|
|
2565
|
+
arc.labelText = text;
|
|
2566
|
+
const labelWidth = Math.min(limit, arc.labelSize.width);
|
|
2567
|
+
const align = this._computeAlign(arc, attribute);
|
|
2568
|
+
const alignOffset = align === 'left' ? labelWidth : align === 'right' ? 0 : labelWidth / 2;
|
|
2569
|
+
const labelRadius = outerRadius - spaceWidth - alignOffset;
|
|
2570
|
+
arc.labelPosition = circlePoint(center.x, center.y, labelRadius, arc.middleAngle);
|
|
2571
|
+
arc.labelLimit = labelWidth;
|
|
2572
|
+
if (!vutils.isGreater(labelWidth, 0)) {
|
|
2573
|
+
arc.labelVisible = false;
|
|
2574
|
+
}
|
|
2575
|
+
arc.angle = arc.middleAngle;
|
|
2576
|
+
});
|
|
2577
|
+
return arcs;
|
|
2578
|
+
}
|
|
2579
|
+
_layoutOutsideLabels(arcs, attribute, currentMarks) {
|
|
2580
|
+
const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
|
|
2581
|
+
const height = center.y * 2;
|
|
2582
|
+
const line2MinLength = attribute.line.line2MinLength;
|
|
2583
|
+
const labelLayout = attribute.layout;
|
|
2584
|
+
const spaceWidth = attribute.spaceWidth;
|
|
2585
|
+
arcs.forEach(arc => {
|
|
2586
|
+
const direction = isQuadrantLeft(arc.quadrant) ? -1 : 1;
|
|
2587
|
+
arc.labelPosition = {
|
|
2588
|
+
x: arc.outerCenter.x + direction * (arc.labelSize.width / 2 + line2MinLength + spaceWidth),
|
|
2589
|
+
y: arc.outerCenter.y
|
|
2590
|
+
};
|
|
2591
|
+
});
|
|
2592
|
+
arcs.sort((a, b) => {
|
|
2593
|
+
return a.labelPosition.y - b.labelPosition.y;
|
|
2594
|
+
});
|
|
2595
|
+
if (attribute.coverEnable !== false || labelLayout.strategy === 'none') {
|
|
2596
|
+
for (const arc of arcs) {
|
|
2597
|
+
const { labelPosition, labelSize } = arc;
|
|
2598
|
+
arc.labelLimit = labelSize.width;
|
|
2599
|
+
arc.pointB = isQuadrantLeft(arc.quadrant)
|
|
2600
|
+
? {
|
|
2601
|
+
x: labelPosition.x + labelSize.width / 2 + line2MinLength + spaceWidth,
|
|
2602
|
+
y: labelPosition.y
|
|
2603
|
+
}
|
|
2604
|
+
: {
|
|
2605
|
+
x: labelPosition.x - labelSize.width / 2 - line2MinLength - spaceWidth,
|
|
2606
|
+
y: labelPosition.y
|
|
2607
|
+
};
|
|
2608
|
+
this._computeX(arc, attribute, currentMarks);
|
|
2609
|
+
}
|
|
2610
|
+
if (attribute.coverEnable === false && labelLayout.strategy === 'none') {
|
|
2611
|
+
this._coverLabels(arcs);
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
else {
|
|
2615
|
+
const maxLabels = height / (attribute.textStyle?.fontSize || 16);
|
|
2616
|
+
this._adjustY(arcs, maxLabels, attribute, currentMarks);
|
|
2617
|
+
const { minY, maxY } = arcs.reduce((yInfo, arc) => {
|
|
2618
|
+
const { y1, y2 } = arc.getLabelBounds();
|
|
2619
|
+
yInfo.minY = Math.max(0, Math.min(y1, yInfo.minY));
|
|
2620
|
+
yInfo.maxY = Math.min(height, Math.max(y2, yInfo.maxY));
|
|
2621
|
+
return yInfo;
|
|
2622
|
+
}, { minY: Infinity, maxY: -Infinity });
|
|
2623
|
+
const halfY = Math.max(Math.abs(height / 2 - minY), Math.abs(maxY - height / 2));
|
|
2624
|
+
const r = this._computeLayoutRadius(halfY, attribute, currentMarks);
|
|
2625
|
+
for (const arc of arcs) {
|
|
2626
|
+
this._computePointB(arc, r, attribute, currentMarks);
|
|
2627
|
+
this._computeX(arc, attribute, currentMarks);
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
const width = center.x * 2;
|
|
2631
|
+
arcs.forEach(arc => {
|
|
2632
|
+
if (arc.labelVisible &&
|
|
2633
|
+
(vutils.isLess(arc.pointB.x, line2MinLength + spaceWidth) ||
|
|
2634
|
+
vutils.isGreater(arc.pointB.x, width - line2MinLength - spaceWidth))) {
|
|
2635
|
+
arc.labelVisible = false;
|
|
2636
|
+
}
|
|
2637
|
+
arc.angle = 0;
|
|
2638
|
+
arc.labelPosition.x = isQuadrantLeft(arc.quadrant)
|
|
2639
|
+
? arc.labelPosition.x
|
|
2640
|
+
: arc.labelPosition.x + 0.5 * arc.labelSize.width;
|
|
2641
|
+
arc.labelLinePath =
|
|
2642
|
+
`M${Math.round(arc.pointA.x)},${Math.round(arc.pointA.y)}` +
|
|
2643
|
+
` L${Math.round(arc.pointB.x)},${Math.round(arc.pointB.y)}` +
|
|
2644
|
+
` L${Math.round(arc.pointC.x)},${Math.round(arc.pointC.y)}`;
|
|
2645
|
+
});
|
|
2646
|
+
return arcs;
|
|
2647
|
+
}
|
|
2648
|
+
_computeX(arc, attribute, currentMarks) {
|
|
2649
|
+
const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
|
|
2650
|
+
const plotLayout = { width: center.x * 2, height: center.y * 2 };
|
|
2651
|
+
const radiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
|
|
2652
|
+
const line1MinLength = attribute.line.line1MinLength;
|
|
2653
|
+
const line2MinLength = attribute.line.line2MinLength;
|
|
2654
|
+
const labelLayoutAlign = attribute.layout?.align;
|
|
2655
|
+
const spaceWidth = attribute.spaceWidth;
|
|
2656
|
+
const align = this._computeAlign(arc, attribute);
|
|
2657
|
+
const { labelPosition, quadrant, pointB } = arc;
|
|
2658
|
+
if (!vutils.isValidNumber(pointB.x * pointB.y)) {
|
|
2659
|
+
arc.pointC = { x: NaN, y: NaN };
|
|
2660
|
+
labelPosition.x = NaN;
|
|
2661
|
+
arc.labelLimit = 0;
|
|
2662
|
+
}
|
|
2663
|
+
const radius = this.computeRadius(radiusRatio, attribute.width, attribute.height);
|
|
2664
|
+
const flag = isQuadrantLeft(quadrant) ? -1 : 1;
|
|
2665
|
+
let cx = 0;
|
|
2666
|
+
const restWidth = flag > 0 ? plotLayout.width - pointB.x : pointB.x;
|
|
2667
|
+
let limit = restWidth - line2MinLength - spaceWidth;
|
|
2668
|
+
if (labelLayoutAlign === 'labelLine') {
|
|
2669
|
+
cx = (radius + line1MinLength + line2MinLength) * flag + center.x;
|
|
2670
|
+
limit = (flag > 0 ? plotLayout.width - cx : cx) - spaceWidth;
|
|
2671
|
+
}
|
|
2672
|
+
const text = this._getFormatLabelText(arc.refDatum, limit);
|
|
2673
|
+
arc.labelText = text;
|
|
2674
|
+
let labelWidth = Math.min(limit, arc.labelSize.width);
|
|
2675
|
+
switch (labelLayoutAlign) {
|
|
2676
|
+
case 'labelLine':
|
|
2677
|
+
break;
|
|
2678
|
+
case 'edge':
|
|
2679
|
+
cx = flag > 0 ? plotLayout.width - labelWidth - spaceWidth : labelWidth + spaceWidth;
|
|
2680
|
+
break;
|
|
2681
|
+
case 'arc':
|
|
2682
|
+
default:
|
|
2683
|
+
cx = pointB.x + flag * line2MinLength;
|
|
2684
|
+
break;
|
|
2685
|
+
}
|
|
2686
|
+
labelWidth = Math.max(this._ellipsisWidth, labelWidth);
|
|
2687
|
+
arc.pointC = { x: cx, y: labelPosition.y };
|
|
2688
|
+
if (labelLayoutAlign === 'edge') {
|
|
2689
|
+
const alignOffset = this._computeAlignOffset(align, labelWidth, -flag);
|
|
2690
|
+
labelPosition.x = flag > 0 ? plotLayout.width + alignOffset : alignOffset;
|
|
2691
|
+
}
|
|
2692
|
+
else {
|
|
2693
|
+
const alignOffset = this._computeAlignOffset(align, labelWidth, flag);
|
|
2694
|
+
labelPosition.x = cx + alignOffset + flag * spaceWidth;
|
|
2695
|
+
}
|
|
2696
|
+
arc.labelLimit = labelWidth;
|
|
2697
|
+
}
|
|
2698
|
+
_computeAlignOffset(align, labelWidth, alignFlag) {
|
|
2699
|
+
switch (align) {
|
|
2700
|
+
case 'left':
|
|
2701
|
+
return alignFlag < 0 ? -labelWidth : 0;
|
|
2702
|
+
case 'right':
|
|
2703
|
+
return alignFlag < 0 ? 0 : labelWidth;
|
|
2704
|
+
case 'center':
|
|
2705
|
+
default:
|
|
2706
|
+
return (labelWidth / 2) * alignFlag;
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
_computeAlign(arc, attribute) {
|
|
2710
|
+
const labelConfig = attribute;
|
|
2711
|
+
const textAlign = labelConfig.textStyle?.textAlign ?? labelConfig.textStyle?.align;
|
|
2712
|
+
const layoutAlign = labelConfig.layout?.textAlign ?? labelConfig.layout?.align;
|
|
2713
|
+
if (labelConfig.position !== 'inside') {
|
|
2714
|
+
if (vutils.isNil(textAlign) || textAlign === 'auto') {
|
|
2715
|
+
if (layoutAlign === 'edge') {
|
|
2716
|
+
return isQuadrantLeft(arc.quadrant) ? 'left' : 'right';
|
|
2717
|
+
}
|
|
2718
|
+
return isQuadrantLeft(arc.quadrant) ? 'right' : 'left';
|
|
2719
|
+
}
|
|
2720
|
+
return textAlign;
|
|
2721
|
+
}
|
|
2722
|
+
return vutils.isNil(textAlign) || textAlign === 'auto' ? 'center' : textAlign;
|
|
2723
|
+
}
|
|
2724
|
+
_getFormatLabelText(value, limit) {
|
|
2725
|
+
return value.text;
|
|
2726
|
+
}
|
|
2727
|
+
_adjustY(arcs, maxLabels, attribute, currentMarks) {
|
|
2728
|
+
const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
|
|
2729
|
+
const plotRect = { width: center.x * 2, height: center.y * 2 };
|
|
2730
|
+
const labelLayout = attribute.layout;
|
|
2731
|
+
if (labelLayout.strategy === 'vertical') {
|
|
2732
|
+
let lastY = 0;
|
|
2733
|
+
let delta;
|
|
2734
|
+
const len = arcs.length;
|
|
2735
|
+
if (len <= 0) {
|
|
2736
|
+
return;
|
|
2737
|
+
}
|
|
2738
|
+
for (let i = 0; i < len; i++) {
|
|
2739
|
+
const { y1 } = arcs[i].getLabelBounds();
|
|
2740
|
+
delta = y1 - lastY;
|
|
2741
|
+
if (vutils.isLess(delta, 0)) {
|
|
2742
|
+
const index = this._shiftY(arcs, i, len - 1, -delta);
|
|
2743
|
+
this._shiftY(arcs, index, 0, delta / 2);
|
|
2744
|
+
}
|
|
2745
|
+
const { y2 } = arcs[i].getLabelBounds();
|
|
2746
|
+
lastY = y2;
|
|
2747
|
+
}
|
|
2748
|
+
const { y1: firstY1 } = arcs[0].getLabelBounds();
|
|
2749
|
+
delta = firstY1 - 0;
|
|
2750
|
+
if (vutils.isLess(delta, 0)) {
|
|
2751
|
+
this._shiftY(arcs, 0, len - 1, -delta);
|
|
2752
|
+
}
|
|
2753
|
+
for (let i = arcs.length - 1; i >= 0; i--) {
|
|
2754
|
+
if (arcs[i].getLabelBounds().y2 > plotRect.height) {
|
|
2755
|
+
arcs[i].labelVisible = false;
|
|
2756
|
+
}
|
|
2757
|
+
else {
|
|
2758
|
+
break;
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
else if (labelLayout.strategy !== 'none') {
|
|
2763
|
+
const priorityArcs = arcs.map((arc, i) => {
|
|
2764
|
+
return {
|
|
2765
|
+
arc,
|
|
2766
|
+
originIndex: i,
|
|
2767
|
+
priorityIndex: 0
|
|
2768
|
+
};
|
|
2769
|
+
});
|
|
2770
|
+
priorityArcs.sort((a, b) => {
|
|
2771
|
+
return b.arc.radian - a.arc.radian;
|
|
2772
|
+
});
|
|
2773
|
+
priorityArcs.forEach((priorityArc, i) => {
|
|
2774
|
+
priorityArc.priorityIndex = i;
|
|
2775
|
+
priorityArc.arc.labelVisible = false;
|
|
2776
|
+
});
|
|
2777
|
+
let topLabelIndex = Infinity;
|
|
2778
|
+
let bottomLabelIndex = -Infinity;
|
|
2779
|
+
for (let i = 0; i < maxLabels && i < arcs.length; i++) {
|
|
2780
|
+
this._storeY(arcs);
|
|
2781
|
+
const arc = priorityArcs[i].arc;
|
|
2782
|
+
this._computeYRange(arc, attribute, currentMarks);
|
|
2783
|
+
arc.labelVisible = true;
|
|
2784
|
+
const curY = arc.labelPosition.y;
|
|
2785
|
+
const { lastIndex, nextIndex } = this._findNeighborIndex(arcs, priorityArcs[i]);
|
|
2786
|
+
const lastArc = arcs[lastIndex];
|
|
2787
|
+
const nextArc = arcs[nextIndex];
|
|
2788
|
+
if (lastIndex === -1 && nextIndex !== -1) {
|
|
2789
|
+
const nextY = nextArc.labelPosition.y;
|
|
2790
|
+
if (curY > nextY) {
|
|
2791
|
+
arc.labelPosition.y = nextY - nextArc.labelSize.height / 2 - arc.labelSize.height / 2;
|
|
2792
|
+
}
|
|
2793
|
+
else {
|
|
2794
|
+
this._twoWayShift(arcs, arc, nextArc, nextIndex);
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
else if (lastIndex !== -1 && nextIndex === -1) {
|
|
2798
|
+
const lastY = lastArc.labelPosition.y;
|
|
2799
|
+
if (curY < lastY) {
|
|
2800
|
+
arc.labelPosition.y = lastY + lastArc.labelSize.height / 2 + arc.labelSize.height / 2;
|
|
2801
|
+
}
|
|
2802
|
+
else {
|
|
2803
|
+
this._twoWayShift(arcs, lastArc, arc, priorityArcs[i].originIndex);
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
else if (lastIndex !== -1 && nextIndex !== -1) {
|
|
2807
|
+
const lastY = lastArc.labelPosition.y;
|
|
2808
|
+
const nextY = nextArc.labelPosition.y;
|
|
2809
|
+
if (curY > nextY) {
|
|
2810
|
+
arc.labelPosition.y = nextY - nextArc.labelSize.height / 2 - arc.labelSize.height / 2;
|
|
2811
|
+
this._twoWayShift(arcs, lastArc, arc, priorityArcs[i].originIndex);
|
|
2812
|
+
}
|
|
2813
|
+
else if (curY < lastY) {
|
|
2814
|
+
arc.labelPosition.y = lastY + lastArc.labelSize.height / 2 + arc.labelSize.height / 2;
|
|
2815
|
+
this._twoWayShift(arcs, arc, nextArc, nextIndex);
|
|
2816
|
+
}
|
|
2817
|
+
else {
|
|
2818
|
+
this._twoWayShift(arcs, lastArc, arc, priorityArcs[i].originIndex);
|
|
2819
|
+
this._twoWayShift(arcs, arc, nextArc, nextIndex);
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
const nextTopIndex = Math.min(topLabelIndex, priorityArcs[i].originIndex);
|
|
2823
|
+
const nextBottomIndex = Math.max(bottomLabelIndex, priorityArcs[i].originIndex);
|
|
2824
|
+
let delta;
|
|
2825
|
+
delta = arcs[nextBottomIndex].getLabelBounds().y2 - plotRect.height;
|
|
2826
|
+
if (vutils.isGreater(delta, 0)) {
|
|
2827
|
+
this._shiftY(arcs, nextBottomIndex, 0, -delta);
|
|
2828
|
+
}
|
|
2829
|
+
delta = arcs[nextTopIndex].getLabelBounds().y1 - 0;
|
|
2830
|
+
if (vutils.isLess(delta, 0)) {
|
|
2831
|
+
this._shiftY(arcs, nextTopIndex, arcs.length - 1, -delta);
|
|
2832
|
+
}
|
|
2833
|
+
delta = arcs[nextBottomIndex].getLabelBounds().y2 - plotRect.height;
|
|
2834
|
+
if (vutils.isGreater(delta, 0)) {
|
|
2835
|
+
arc.labelVisible = false;
|
|
2836
|
+
this._restoreY(arcs);
|
|
2837
|
+
break;
|
|
2838
|
+
}
|
|
2839
|
+
else if (labelLayout.tangentConstraint && !this._checkYRange(arcs)) {
|
|
2840
|
+
arc.labelVisible = false;
|
|
2841
|
+
this._restoreY(arcs);
|
|
2842
|
+
}
|
|
2843
|
+
else {
|
|
2844
|
+
topLabelIndex = nextTopIndex;
|
|
2845
|
+
bottomLabelIndex = nextBottomIndex;
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
_shiftY(arcs, start, end, delta) {
|
|
2851
|
+
const direction = start < end ? 1 : -1;
|
|
2852
|
+
let index = start;
|
|
2853
|
+
while (index !== -1) {
|
|
2854
|
+
arcs[index].labelPosition.y += delta;
|
|
2855
|
+
const nextIndex = this._findNextVisibleIndex(arcs, index, end, direction);
|
|
2856
|
+
if (nextIndex >= 0 && nextIndex < arcs.length) {
|
|
2857
|
+
const { y1: curY1, y2: curY2 } = arcs[index].getLabelBounds();
|
|
2858
|
+
const { y1: nextY1, y2: nextY2 } = arcs[nextIndex].getLabelBounds();
|
|
2859
|
+
if ((direction > 0 && curY2 < nextY1) || (direction < 0 && curY1 > nextY2)) {
|
|
2860
|
+
return index;
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2863
|
+
index = nextIndex;
|
|
2864
|
+
}
|
|
2865
|
+
return end;
|
|
2866
|
+
}
|
|
2867
|
+
_findNextVisibleIndex(arcs, start, end, direction) {
|
|
2868
|
+
const diff = (end - start) * direction;
|
|
2869
|
+
for (let i = 1; i <= diff; i++) {
|
|
2870
|
+
const index = start + i * direction;
|
|
2871
|
+
if (arcs[index].labelVisible) {
|
|
2872
|
+
return index;
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
return -1;
|
|
2876
|
+
}
|
|
2877
|
+
_computePointB(arc, r, attribute, currentMarks) {
|
|
2878
|
+
const labelConfig = attribute;
|
|
2879
|
+
const radiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
|
|
2880
|
+
const line1MinLength = labelConfig.line.line1MinLength;
|
|
2881
|
+
const labelLayout = labelConfig.layout;
|
|
2882
|
+
if (labelLayout.strategy === 'none') {
|
|
2883
|
+
arc.pointB = {
|
|
2884
|
+
x: arc.outerCenter.x,
|
|
2885
|
+
y: arc.outerCenter.y
|
|
2886
|
+
};
|
|
2887
|
+
}
|
|
2888
|
+
else {
|
|
2889
|
+
const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
|
|
2890
|
+
const radius = this.computeRadius(radiusRatio, attribute.width, attribute.height);
|
|
2891
|
+
const { labelPosition, quadrant } = arc;
|
|
2892
|
+
const outerR = Math.max(radius + line1MinLength, currentMarks[0].attribute.outerRadius);
|
|
2893
|
+
const rd = r - outerR;
|
|
2894
|
+
const x = Math.sqrt(r ** 2 - Math.abs(center.y - labelPosition.y) ** 2) - rd;
|
|
2895
|
+
if (vutils.isValidNumber(x)) {
|
|
2896
|
+
arc.pointB = {
|
|
2897
|
+
x: center.x + x * (isQuadrantLeft(quadrant) ? -1 : 1),
|
|
2898
|
+
y: labelPosition.y
|
|
2899
|
+
};
|
|
2900
|
+
}
|
|
2901
|
+
else {
|
|
2902
|
+
arc.pointB = { x: NaN, y: NaN };
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
_storeY(arcs) {
|
|
2907
|
+
for (const arc of arcs) {
|
|
2908
|
+
if (arc.labelVisible) {
|
|
2909
|
+
arc.lastLabelY = arc.labelPosition.y;
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
_computeYRange(arc, attribute, currentMarks) {
|
|
2914
|
+
const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
|
|
2915
|
+
const plotRect = { width: center.x * 2, height: center.y * 2 };
|
|
2916
|
+
const radiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
|
|
2917
|
+
const line1MinLength = attribute.line.line1MinLength;
|
|
2918
|
+
const { width, height } = plotRect;
|
|
2919
|
+
const radius = this.computeRadius(radiusRatio, attribute.width, attribute.height);
|
|
2920
|
+
const r = this._computeLayoutRadius(height / 2, attribute, currentMarks);
|
|
2921
|
+
const cx = Math.abs(arc.center.x - width / 2);
|
|
2922
|
+
const cy = arc.center.y - height / 2;
|
|
2923
|
+
let a;
|
|
2924
|
+
let b;
|
|
2925
|
+
let c;
|
|
2926
|
+
if (vutils.isNumberClose(width / 2, cx)) {
|
|
2927
|
+
a = 0;
|
|
2928
|
+
b = 1;
|
|
2929
|
+
c = -cy;
|
|
2930
|
+
}
|
|
2931
|
+
else if (vutils.isNumberClose(height / 2, cy)) {
|
|
2932
|
+
a = 1;
|
|
2933
|
+
b = 0;
|
|
2934
|
+
c = -cx;
|
|
2935
|
+
}
|
|
2936
|
+
else {
|
|
2937
|
+
const k = -1 / (cy / cx);
|
|
2938
|
+
a = k;
|
|
2939
|
+
b = -1;
|
|
2940
|
+
c = cy - k * cx;
|
|
2941
|
+
}
|
|
2942
|
+
const points = lineCirclePoints(a, b, c, line1MinLength + radius - r, 0, r);
|
|
2943
|
+
if (points.length < 2) {
|
|
2944
|
+
return;
|
|
2945
|
+
}
|
|
2946
|
+
let min;
|
|
2947
|
+
let max;
|
|
2948
|
+
if (points[0].x > points[1].x) {
|
|
2949
|
+
points.reverse();
|
|
2950
|
+
}
|
|
2951
|
+
if (points[0].x < 0) {
|
|
2952
|
+
if (vutils.isNumberClose(points[0].y, points[1].y)) {
|
|
2953
|
+
if (Math.abs(arc.middleAngle) < Math.PI / 2) {
|
|
2954
|
+
min = 0;
|
|
2955
|
+
max = points[1].y + height / 2;
|
|
2956
|
+
}
|
|
2957
|
+
else {
|
|
2958
|
+
min = points[1].y + height / 2;
|
|
2959
|
+
max = height;
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
else if (points[0].y < points[1].y) {
|
|
2963
|
+
min = 0;
|
|
2964
|
+
max = points[1].y + height / 2;
|
|
2965
|
+
}
|
|
2966
|
+
else {
|
|
2967
|
+
min = points[1].y + height / 2;
|
|
2968
|
+
max = plotRect.height;
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
else {
|
|
2972
|
+
min = Math.min(points[0].y, points[1].y) + height / 2;
|
|
2973
|
+
max = Math.max(points[0].y, points[1].y) + height / 2;
|
|
2974
|
+
}
|
|
2975
|
+
arc.labelYRange = [min, max];
|
|
2976
|
+
}
|
|
2977
|
+
_computeLayoutRadius(halfYLength, attribute, currentMarks) {
|
|
2978
|
+
const labelConfig = attribute;
|
|
2979
|
+
const layoutArcGap = labelConfig.layoutArcGap;
|
|
2980
|
+
const line1MinLength = labelConfig.line.line1MinLength;
|
|
2981
|
+
const radiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
|
|
2982
|
+
const radius = this.computeRadius(radiusRatio, attribute.width, attribute.height);
|
|
2983
|
+
const outerR = radius + line1MinLength;
|
|
2984
|
+
const a = outerR - layoutArcGap;
|
|
2985
|
+
return Math.max((a ** 2 + halfYLength ** 2) / (2 * a), outerR);
|
|
2986
|
+
}
|
|
2987
|
+
_findNeighborIndex(arcs, priorityArc) {
|
|
2988
|
+
const index = priorityArc.originIndex;
|
|
2989
|
+
let lastIndex = -1;
|
|
2990
|
+
let nextIndex = -1;
|
|
2991
|
+
for (let i = index - 1; i >= 0; i--) {
|
|
2992
|
+
if (arcs[i].labelVisible) {
|
|
2993
|
+
lastIndex = i;
|
|
2994
|
+
break;
|
|
2995
|
+
}
|
|
2996
|
+
}
|
|
2997
|
+
for (let i = index + 1; i < arcs.length; i++) {
|
|
2998
|
+
if (arcs[i].labelVisible) {
|
|
2999
|
+
nextIndex = i;
|
|
3000
|
+
break;
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
return {
|
|
3004
|
+
lastIndex,
|
|
3005
|
+
nextIndex
|
|
3006
|
+
};
|
|
3007
|
+
}
|
|
3008
|
+
_twoWayShift(arcs, lastArc, nextArc, nextIndex) {
|
|
3009
|
+
const delta = nextArc.getLabelBounds().y1 - lastArc.getLabelBounds().y2;
|
|
3010
|
+
if (vutils.isLess(delta, 0)) {
|
|
3011
|
+
const i = this._shiftY(arcs, nextIndex, arcs.length - 1, -delta);
|
|
3012
|
+
this._shiftY(arcs, i, 0, delta / 2);
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
3015
|
+
_restoreY(arcs) {
|
|
3016
|
+
for (const arc of arcs) {
|
|
3017
|
+
if (arc.labelVisible) {
|
|
3018
|
+
arc.labelPosition.y = arc.lastLabelY;
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
_checkYRange(arcs) {
|
|
3023
|
+
for (const arc of arcs) {
|
|
3024
|
+
const { labelYRange, labelPosition } = arc;
|
|
3025
|
+
if (arc.labelVisible &&
|
|
3026
|
+
labelYRange &&
|
|
3027
|
+
(vutils.isLess(labelPosition.y, labelYRange[0]) || vutils.isGreater(labelPosition.y, labelYRange[1]))) {
|
|
3028
|
+
return false;
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
return true;
|
|
3032
|
+
}
|
|
3033
|
+
_coverLabels(arcs) {
|
|
3034
|
+
if (arcs.length <= 1) {
|
|
3035
|
+
return;
|
|
3036
|
+
}
|
|
3037
|
+
let lastBounds = arcs[0].getLabelBounds();
|
|
3038
|
+
for (let i = 1; i < arcs.length; i++) {
|
|
3039
|
+
const bounds = arcs[i].getLabelBounds();
|
|
3040
|
+
if (!checkBoundsOverlap(lastBounds, bounds)) {
|
|
3041
|
+
lastBounds = bounds;
|
|
3042
|
+
}
|
|
3043
|
+
else {
|
|
3044
|
+
arcs[i].labelVisible = false;
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
computeRadius(r, width, height, k) {
|
|
3049
|
+
return this.computeLayoutRadius(width ? width : 0, height ? height : 0) * r * (vutils.isNil(k) ? 1 : k);
|
|
3050
|
+
}
|
|
3051
|
+
computeLayoutRadius(width, height) {
|
|
3052
|
+
return Math.min(width / 2, height / 2);
|
|
3053
|
+
}
|
|
3054
|
+
computeLayoutOuterRadius(r, width, height) {
|
|
3055
|
+
return r / (Math.min(width, height) / 2);
|
|
3056
|
+
}
|
|
3057
|
+
computeDatumRadius(width, height, outerRadius) {
|
|
3058
|
+
const outerRadiusRatio = this.computeLayoutOuterRadius(outerRadius, width, height);
|
|
3059
|
+
return this.computeLayoutRadius(width ? width : 0, height ? height : 0) * outerRadiusRatio;
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
|
|
2225
3063
|
const labelComponentMap = {
|
|
2226
3064
|
rect: RectLabel,
|
|
2227
|
-
symbol: SymbolLabel
|
|
3065
|
+
symbol: SymbolLabel,
|
|
3066
|
+
arc: ArcLabel
|
|
2228
3067
|
};
|
|
2229
3068
|
class DataLabel extends AbstractComponent {
|
|
2230
3069
|
name = 'data-label';
|
|
@@ -2619,6 +3458,7 @@
|
|
|
2619
3458
|
AXIS_ELEMENT_NAME["gridRegion"] = "axis-grid-region";
|
|
2620
3459
|
AXIS_ELEMENT_NAME["line"] = "axis-line";
|
|
2621
3460
|
AXIS_ELEMENT_NAME["background"] = "axis-background";
|
|
3461
|
+
AXIS_ELEMENT_NAME["axisLabelBackground"] = "axis-label-background";
|
|
2622
3462
|
})(exports.AXIS_ELEMENT_NAME || (exports.AXIS_ELEMENT_NAME = {}));
|
|
2623
3463
|
exports.AxisStateValue = void 0;
|
|
2624
3464
|
(function (AxisStateValue) {
|
|
@@ -2801,7 +3641,7 @@
|
|
|
2801
3641
|
}
|
|
2802
3642
|
};
|
|
2803
3643
|
_renderInner(container) {
|
|
2804
|
-
const { title, label, tick, line, grid, items
|
|
3644
|
+
const { title, label, tick, line, grid, items } = this.attribute;
|
|
2805
3645
|
const axisContainer = vrender.createGroup({ x: 0, y: 0, zIndex: 1 });
|
|
2806
3646
|
axisContainer.name = exports.AXIS_ELEMENT_NAME.axisContainer;
|
|
2807
3647
|
axisContainer.id = this._getNodeId('container');
|
|
@@ -2825,7 +3665,9 @@
|
|
|
2825
3665
|
items.forEach((axisItems, layer) => {
|
|
2826
3666
|
const layerLabelGroup = this.renderLabels(labelGroup, axisItems, layer);
|
|
2827
3667
|
const labels = layerLabelGroup.getChildren();
|
|
2828
|
-
this.
|
|
3668
|
+
this.beforeLabelsOverlap(labels, axisItems, layerLabelGroup, layer, items.length);
|
|
3669
|
+
this.handleLabelsOverlap(labels, axisItems, layerLabelGroup, layer, items.length);
|
|
3670
|
+
this.afterLabelsOverlap(labels, axisItems, layerLabelGroup, layer, items.length);
|
|
2829
3671
|
});
|
|
2830
3672
|
}
|
|
2831
3673
|
if (grid?.visible) {
|
|
@@ -2835,22 +3677,6 @@
|
|
|
2835
3677
|
if (title?.visible) {
|
|
2836
3678
|
this.renderTitle(axisContainer);
|
|
2837
3679
|
}
|
|
2838
|
-
if (panel && panel.visible) {
|
|
2839
|
-
const axisContainerBounds = axisContainer.AABBBounds;
|
|
2840
|
-
const bgRect = vrender.createRect({
|
|
2841
|
-
x: axisContainerBounds.x1,
|
|
2842
|
-
y: axisContainerBounds.y1,
|
|
2843
|
-
width: axisContainerBounds.width(),
|
|
2844
|
-
height: axisContainerBounds.height(),
|
|
2845
|
-
...panel.style
|
|
2846
|
-
});
|
|
2847
|
-
bgRect.name = exports.AXIS_ELEMENT_NAME.background;
|
|
2848
|
-
bgRect.id = this._getNodeId('background');
|
|
2849
|
-
if (!vutils.isEmpty(panel.state)) {
|
|
2850
|
-
bgRect.states = vutils.merge({}, DEFAULT_STATES$2, panel.state);
|
|
2851
|
-
}
|
|
2852
|
-
axisContainer.insertBefore(bgRect, axisContainer.firstChild);
|
|
2853
|
-
}
|
|
2854
3680
|
}
|
|
2855
3681
|
renderTicks(container) {
|
|
2856
3682
|
const tickLineItems = this.getTickLineItems();
|
|
@@ -2865,7 +3691,7 @@
|
|
|
2865
3691
|
line.name = exports.AXIS_ELEMENT_NAME.tick;
|
|
2866
3692
|
line.id = this._getNodeId(item.id);
|
|
2867
3693
|
if (vutils.isEmpty(this.attribute.tick?.state)) {
|
|
2868
|
-
line.states =
|
|
3694
|
+
line.states = DEFAULT_STATES$2;
|
|
2869
3695
|
}
|
|
2870
3696
|
else {
|
|
2871
3697
|
const data = this.data[index];
|
|
@@ -2891,7 +3717,7 @@
|
|
|
2891
3717
|
line.name = exports.AXIS_ELEMENT_NAME.subTick;
|
|
2892
3718
|
line.id = this._getNodeId(`${index}`);
|
|
2893
3719
|
if (vutils.isEmpty(subTick.state)) {
|
|
2894
|
-
line.states =
|
|
3720
|
+
line.states = DEFAULT_STATES$2;
|
|
2895
3721
|
}
|
|
2896
3722
|
else {
|
|
2897
3723
|
const subTickLineState = vutils.merge({}, DEFAULT_STATES$2, subTick.state);
|
|
@@ -2928,7 +3754,7 @@
|
|
|
2928
3754
|
text.name = exports.AXIS_ELEMENT_NAME.label;
|
|
2929
3755
|
text.id = this._getNodeId(`layer${layer}-label-${item.id}`);
|
|
2930
3756
|
if (vutils.isEmpty(this.attribute.label?.state)) {
|
|
2931
|
-
text.states =
|
|
3757
|
+
text.states = DEFAULT_STATES$2;
|
|
2932
3758
|
}
|
|
2933
3759
|
else {
|
|
2934
3760
|
const labelState = vutils.merge({}, DEFAULT_STATES$2, this.attribute.label.state);
|
|
@@ -2984,7 +3810,17 @@
|
|
|
2984
3810
|
getTextAlign(vector) {
|
|
2985
3811
|
let align = 'center';
|
|
2986
3812
|
if (vutils.isNumberClose(vector[0], 0)) {
|
|
2987
|
-
|
|
3813
|
+
if (vutils.isNumberClose(vector[1], 0)) {
|
|
3814
|
+
if (Object.is(vector[1], -0)) {
|
|
3815
|
+
align = 'start';
|
|
3816
|
+
}
|
|
3817
|
+
else if (Object.is(vector[0], -0)) {
|
|
3818
|
+
align = 'end';
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
else {
|
|
3822
|
+
align = 'center';
|
|
3823
|
+
}
|
|
2988
3824
|
}
|
|
2989
3825
|
else if (vector[0] > 0) {
|
|
2990
3826
|
align = 'start';
|
|
@@ -3112,7 +3948,7 @@
|
|
|
3112
3948
|
}
|
|
3113
3949
|
const point = this.getVerticalCoord(tickDatum.point, offset, inside);
|
|
3114
3950
|
const vector = this.getVerticalVector(offset, inside, point);
|
|
3115
|
-
const text = formatMethod ? formatMethod(tickDatum.label
|
|
3951
|
+
const text = formatMethod ? formatMethod(`${tickDatum.label}`, tickDatum, index, tickData, layer) : tickDatum.label;
|
|
3116
3952
|
let { style: textStyle } = tagAttributes;
|
|
3117
3953
|
textStyle = vutils.isFunction(textStyle)
|
|
3118
3954
|
? vutils.merge({}, DEFAULT_AXIS_THEME.label.style, textStyle(tickDatum, index, tickData, layer))
|
|
@@ -3373,18 +4209,90 @@
|
|
|
3373
4209
|
return;
|
|
3374
4210
|
}
|
|
3375
4211
|
labels.forEach(label => {
|
|
3376
|
-
|
|
4212
|
+
if ((orient === 'top' || orient === 'bottom') && Math.floor(label.AABBBounds.height()) <= limitLength) {
|
|
4213
|
+
return;
|
|
4214
|
+
}
|
|
4215
|
+
if ((orient === 'left' || orient === 'right') && Math.floor(label.AABBBounds.width()) <= limitLength) {
|
|
4216
|
+
return;
|
|
4217
|
+
}
|
|
4218
|
+
let limitLabelLength = label.attribute.angle === 0 || vutils.isNil(label.attribute.angle)
|
|
3377
4219
|
? orient === 'top' || orient === 'bottom'
|
|
3378
4220
|
? null
|
|
3379
4221
|
: limitLength
|
|
3380
4222
|
: Math.abs(limitLength / Math.sin(label.attribute.angle));
|
|
4223
|
+
if (vutils.isValidNumber(label.attribute.maxLineWidth)) {
|
|
4224
|
+
limitLabelLength = vutils.isValidNumber(limitLabelLength)
|
|
4225
|
+
? Math.min(label.attribute.maxLineWidth, limitLabelLength)
|
|
4226
|
+
: label.attribute.maxLineWidth;
|
|
4227
|
+
}
|
|
3381
4228
|
label.setAttributes({
|
|
3382
4229
|
maxLineWidth: limitLabelLength,
|
|
3383
|
-
ellipsis
|
|
4230
|
+
ellipsis: label.attribute.ellipsis || ellipsis
|
|
3384
4231
|
});
|
|
3385
4232
|
});
|
|
3386
4233
|
}
|
|
3387
4234
|
|
|
4235
|
+
function alignAxisLabels(labels, start, containerSize, orient, align) {
|
|
4236
|
+
if (orient === 'right' || orient === 'left') {
|
|
4237
|
+
if (align === 'left') {
|
|
4238
|
+
const flag = orient === 'right' ? 0 : -1;
|
|
4239
|
+
labels.forEach(label => {
|
|
4240
|
+
label.setAttributes({
|
|
4241
|
+
x: start + containerSize * flag,
|
|
4242
|
+
textAlign: 'left'
|
|
4243
|
+
});
|
|
4244
|
+
});
|
|
4245
|
+
}
|
|
4246
|
+
else if (align === 'right') {
|
|
4247
|
+
const flag = orient === 'right' ? 1 : 0;
|
|
4248
|
+
labels.forEach(label => {
|
|
4249
|
+
label.setAttributes({
|
|
4250
|
+
x: start + containerSize * flag,
|
|
4251
|
+
textAlign: 'right'
|
|
4252
|
+
});
|
|
4253
|
+
});
|
|
4254
|
+
}
|
|
4255
|
+
else if (align === 'center') {
|
|
4256
|
+
const flag = orient === 'right' ? 1 : -1;
|
|
4257
|
+
labels.forEach(label => {
|
|
4258
|
+
label.setAttributes({
|
|
4259
|
+
x: start + containerSize * 0.5 * flag,
|
|
4260
|
+
textAlign: 'center'
|
|
4261
|
+
});
|
|
4262
|
+
});
|
|
4263
|
+
}
|
|
4264
|
+
}
|
|
4265
|
+
else if (orient === 'bottom' || orient === 'top') {
|
|
4266
|
+
if (align === 'top') {
|
|
4267
|
+
const flag = orient === 'bottom' ? 0 : -1;
|
|
4268
|
+
labels.forEach(label => {
|
|
4269
|
+
label.setAttributes({
|
|
4270
|
+
y: start + containerSize * flag,
|
|
4271
|
+
textBaseline: 'top'
|
|
4272
|
+
});
|
|
4273
|
+
});
|
|
4274
|
+
}
|
|
4275
|
+
else if (align === 'bottom') {
|
|
4276
|
+
const flag = orient === 'bottom' ? 1 : 0;
|
|
4277
|
+
labels.forEach(label => {
|
|
4278
|
+
label.setAttributes({
|
|
4279
|
+
y: start + containerSize * flag,
|
|
4280
|
+
textBaseline: 'bottom'
|
|
4281
|
+
});
|
|
4282
|
+
});
|
|
4283
|
+
}
|
|
4284
|
+
else if (align === 'middle') {
|
|
4285
|
+
const flag = orient === 'bottom' ? 1 : -1;
|
|
4286
|
+
labels.forEach(label => {
|
|
4287
|
+
label.setAttributes({
|
|
4288
|
+
y: start + containerSize * 0.5 * flag,
|
|
4289
|
+
textBaseline: 'middle'
|
|
4290
|
+
});
|
|
4291
|
+
});
|
|
4292
|
+
}
|
|
4293
|
+
}
|
|
4294
|
+
}
|
|
4295
|
+
|
|
3388
4296
|
function getCirclePoints(center, count, radius, startAngle, endAngle) {
|
|
3389
4297
|
const points = [];
|
|
3390
4298
|
const range = endAngle - startAngle;
|
|
@@ -3402,6 +4310,25 @@
|
|
|
3402
4310
|
this.setMode(mode);
|
|
3403
4311
|
}
|
|
3404
4312
|
}
|
|
4313
|
+
_renderInner(container) {
|
|
4314
|
+
super._renderInner(container);
|
|
4315
|
+
const { panel } = this.attribute;
|
|
4316
|
+
if (panel && panel.visible) {
|
|
4317
|
+
const axisContainer = this.axisContainer;
|
|
4318
|
+
const axisContainerBounds = axisContainer.AABBBounds;
|
|
4319
|
+
const bgRect = vrender.createRect({
|
|
4320
|
+
x: axisContainerBounds.x1,
|
|
4321
|
+
y: axisContainerBounds.y1,
|
|
4322
|
+
width: axisContainerBounds.width(),
|
|
4323
|
+
height: axisContainerBounds.height(),
|
|
4324
|
+
...panel.style
|
|
4325
|
+
});
|
|
4326
|
+
bgRect.name = exports.AXIS_ELEMENT_NAME.background;
|
|
4327
|
+
bgRect.id = this._getNodeId('background');
|
|
4328
|
+
bgRect.states = vutils.merge({}, DEFAULT_STATES$1, panel.state ?? {});
|
|
4329
|
+
axisContainer.insertBefore(bgRect, axisContainer.firstChild);
|
|
4330
|
+
}
|
|
4331
|
+
}
|
|
3405
4332
|
renderLine(container) {
|
|
3406
4333
|
const { start, end, line } = this.attribute;
|
|
3407
4334
|
const { startSymbol, endSymbol, style, breakRange, breakShape, breakShapeStyle, state, ...restLineAttrs } = line;
|
|
@@ -3566,13 +4493,11 @@
|
|
|
3566
4493
|
textBaseline,
|
|
3567
4494
|
...textStyle
|
|
3568
4495
|
},
|
|
3569
|
-
state:
|
|
3570
|
-
|
|
3571
|
-
: {
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
panel: state.background
|
|
3575
|
-
}
|
|
4496
|
+
state: {
|
|
4497
|
+
text: vutils.merge({}, DEFAULT_STATES$1, state?.text),
|
|
4498
|
+
shape: vutils.merge({}, DEFAULT_STATES$1, state?.shape),
|
|
4499
|
+
panel: vutils.merge({}, DEFAULT_STATES$1, state?.background)
|
|
4500
|
+
}
|
|
3576
4501
|
};
|
|
3577
4502
|
attrs.angle = angle;
|
|
3578
4503
|
if (shape && shape.visible) {
|
|
@@ -3694,7 +4619,7 @@
|
|
|
3694
4619
|
const { verticalFactor = 1 } = this.attribute;
|
|
3695
4620
|
const factor = (inside ? 1 : -1) * verticalFactor;
|
|
3696
4621
|
if (vutils.isNumberClose(vector[1], 0)) {
|
|
3697
|
-
if (vutils.isNumberClose(vector[0], 0)) {
|
|
4622
|
+
if (vutils.isNumberClose(vector[0], 0) && !Object.is(vector[0], -0) && !Object.is(vector[1], -0)) {
|
|
3698
4623
|
base = factor === 1 ? 'bottom' : 'top';
|
|
3699
4624
|
}
|
|
3700
4625
|
else {
|
|
@@ -3709,24 +4634,21 @@
|
|
|
3709
4634
|
}
|
|
3710
4635
|
return base;
|
|
3711
4636
|
}
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
4637
|
+
beforeLabelsOverlap(labelShapes, labelData, labelContainer, layer, layerCount) {
|
|
4638
|
+
const orient = this.attribute.orient;
|
|
4639
|
+
if (orient === 'left' || orient === 'right') {
|
|
4640
|
+
rotateYAxis(orient, labelShapes);
|
|
3715
4641
|
}
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
let limitLength = verticalLimitSize;
|
|
3719
|
-
let titleHeight = 0;
|
|
3720
|
-
let titleSpacing = 0;
|
|
3721
|
-
const axisLineWidth = line?.visible ? line.style.lineWidth ?? 1 : 0;
|
|
3722
|
-
const tickLength = tick?.visible ? tick.length ?? 4 : 0;
|
|
3723
|
-
if (title?.visible) {
|
|
3724
|
-
titleHeight = measureTextSize(title.text, title.textStyle).height;
|
|
3725
|
-
titleSpacing = title.space;
|
|
4642
|
+
else if (orient === 'bottom' || orient === 'top') {
|
|
4643
|
+
rotateXAxis(orient, labelShapes);
|
|
3726
4644
|
}
|
|
3727
|
-
|
|
3728
|
-
|
|
4645
|
+
}
|
|
4646
|
+
handleLabelsOverlap(labelShapes, labelData, labelContainer, layer, layerCount) {
|
|
4647
|
+
if (vutils.isEmpty(labelShapes)) {
|
|
4648
|
+
return;
|
|
3729
4649
|
}
|
|
4650
|
+
const { verticalLimitSize, label, orient } = this.attribute;
|
|
4651
|
+
const limitLength = this._getAxisLabelLimitLength(verticalLimitSize, layerCount);
|
|
3730
4652
|
const { layoutFunc, autoRotate: autoRotate$1, autoRotateAngle, autoLimit: autoLimit$1, limitEllipsis, autoHide: autoHide$1, autoHideMethod, autoHideSeparation } = label;
|
|
3731
4653
|
if (vutils.isFunction(layoutFunc)) {
|
|
3732
4654
|
layoutFunc(labelShapes, labelData, layer, this);
|
|
@@ -3754,6 +4676,79 @@
|
|
|
3754
4676
|
}
|
|
3755
4677
|
}
|
|
3756
4678
|
}
|
|
4679
|
+
afterLabelsOverlap(labelShapes, labelData, labelContainer, layer, layerCount) {
|
|
4680
|
+
const { verticalLimitSize, orient } = this.attribute;
|
|
4681
|
+
const isHorizontal = orient === 'bottom' || orient === 'top';
|
|
4682
|
+
const axisLabelContainerBounds = labelContainer.AABBBounds;
|
|
4683
|
+
let axisLabelContainerSize = isHorizontal ? axisLabelContainerBounds.height() : axisLabelContainerBounds.width();
|
|
4684
|
+
const { verticalMinSize } = this.attribute;
|
|
4685
|
+
if (vutils.isValidNumber(verticalMinSize) && (!vutils.isValidNumber(verticalLimitSize) || verticalMinSize <= verticalLimitSize)) {
|
|
4686
|
+
const minSize = this._getAxisLabelLimitLength(verticalMinSize, layerCount);
|
|
4687
|
+
axisLabelContainerSize = Math.max(axisLabelContainerSize, minSize);
|
|
4688
|
+
let x;
|
|
4689
|
+
let y;
|
|
4690
|
+
if (orient === 'left') {
|
|
4691
|
+
x = axisLabelContainerBounds.x2 - axisLabelContainerSize;
|
|
4692
|
+
y = axisLabelContainerBounds.y1;
|
|
4693
|
+
}
|
|
4694
|
+
else if (orient === 'right') {
|
|
4695
|
+
x = axisLabelContainerBounds.x1;
|
|
4696
|
+
y = axisLabelContainerBounds.y1;
|
|
4697
|
+
}
|
|
4698
|
+
else if (orient === 'top') {
|
|
4699
|
+
x = axisLabelContainerBounds.x1;
|
|
4700
|
+
y = axisLabelContainerBounds.y2 - axisLabelContainerSize;
|
|
4701
|
+
}
|
|
4702
|
+
else if (orient === 'bottom') {
|
|
4703
|
+
x = axisLabelContainerBounds.x1;
|
|
4704
|
+
y = axisLabelContainerBounds.y1;
|
|
4705
|
+
}
|
|
4706
|
+
const bgRect = vrender.createRect({
|
|
4707
|
+
x,
|
|
4708
|
+
y,
|
|
4709
|
+
width: isHorizontal ? axisLabelContainerBounds.width() : axisLabelContainerSize,
|
|
4710
|
+
height: isHorizontal ? axisLabelContainerSize : axisLabelContainerBounds.height(),
|
|
4711
|
+
pickable: false
|
|
4712
|
+
});
|
|
4713
|
+
bgRect.name = exports.AXIS_ELEMENT_NAME.axisLabelBackground;
|
|
4714
|
+
bgRect.id = this._getNodeId('axis-label-background');
|
|
4715
|
+
labelContainer.insertBefore(bgRect, labelContainer.firstChild);
|
|
4716
|
+
}
|
|
4717
|
+
if (vutils.isValid(this.attribute.label.containerAlign)) {
|
|
4718
|
+
let start;
|
|
4719
|
+
if (orient === 'left') {
|
|
4720
|
+
start = axisLabelContainerBounds.x2;
|
|
4721
|
+
}
|
|
4722
|
+
else if (orient === 'right') {
|
|
4723
|
+
start = axisLabelContainerBounds.x1;
|
|
4724
|
+
}
|
|
4725
|
+
else if (orient === 'top') {
|
|
4726
|
+
start = axisLabelContainerBounds.y2;
|
|
4727
|
+
}
|
|
4728
|
+
else if (orient === 'bottom') {
|
|
4729
|
+
start = axisLabelContainerBounds.y1;
|
|
4730
|
+
}
|
|
4731
|
+
alignAxisLabels(labelShapes, start, axisLabelContainerSize, orient, this.attribute.label.containerAlign);
|
|
4732
|
+
}
|
|
4733
|
+
}
|
|
4734
|
+
_getAxisLabelLimitLength(limitSize, layerCount) {
|
|
4735
|
+
const { label, title, line, tick } = this.attribute;
|
|
4736
|
+
const labelSpace = label.space ?? 4;
|
|
4737
|
+
let limitLength = limitSize;
|
|
4738
|
+
let titleHeight = 0;
|
|
4739
|
+
let titleSpacing = 0;
|
|
4740
|
+
const axisLineWidth = line?.visible ? line.style.lineWidth ?? 1 : 0;
|
|
4741
|
+
const tickLength = tick?.visible ? tick.length ?? 4 : 0;
|
|
4742
|
+
if (title?.visible) {
|
|
4743
|
+
titleHeight = measureTextSize(title.text, title.textStyle).height;
|
|
4744
|
+
const padding = vutils.normalizePadding(title.padding);
|
|
4745
|
+
titleSpacing = title.space + padding[0] + padding[2];
|
|
4746
|
+
}
|
|
4747
|
+
if (limitLength) {
|
|
4748
|
+
limitLength = (limitLength - labelSpace - titleSpacing - titleHeight - axisLineWidth - tickLength) / layerCount;
|
|
4749
|
+
}
|
|
4750
|
+
return limitLength;
|
|
4751
|
+
}
|
|
3757
4752
|
}
|
|
3758
4753
|
|
|
3759
4754
|
class CircleAxis extends AxisBase {
|
|
@@ -3850,13 +4845,11 @@
|
|
|
3850
4845
|
textAlign: 'center',
|
|
3851
4846
|
...textStyle
|
|
3852
4847
|
},
|
|
3853
|
-
state:
|
|
3854
|
-
|
|
3855
|
-
: {
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
panel: state.background
|
|
3859
|
-
}
|
|
4848
|
+
state: {
|
|
4849
|
+
text: vutils.merge({}, DEFAULT_STATES$1, state?.text),
|
|
4850
|
+
shape: vutils.merge({}, DEFAULT_STATES$1, state?.shape),
|
|
4851
|
+
panel: vutils.merge({}, DEFAULT_STATES$1, state?.background)
|
|
4852
|
+
}
|
|
3860
4853
|
};
|
|
3861
4854
|
const { angle } = restAttrs;
|
|
3862
4855
|
attrs.angle = angle;
|
|
@@ -4008,7 +5001,13 @@
|
|
|
4008
5001
|
}
|
|
4009
5002
|
return base;
|
|
4010
5003
|
}
|
|
4011
|
-
|
|
5004
|
+
beforeLabelsOverlap(labelShapes, labelData, labelContainer, layer, layerCount) {
|
|
5005
|
+
return;
|
|
5006
|
+
}
|
|
5007
|
+
handleLabelsOverlap(labelShapes, labelData, labelContainer, layer, layerCount) {
|
|
5008
|
+
return;
|
|
5009
|
+
}
|
|
5010
|
+
afterLabelsOverlap(labelShapes, labelData, labelContainer, layer, layerCount) {
|
|
4012
5011
|
return;
|
|
4013
5012
|
}
|
|
4014
5013
|
}
|
|
@@ -8915,6 +9914,17 @@
|
|
|
8915
9914
|
}
|
|
8916
9915
|
}
|
|
8917
9916
|
|
|
9917
|
+
exports.IOperateType = void 0;
|
|
9918
|
+
(function (IOperateType) {
|
|
9919
|
+
IOperateType["drawStart"] = "drawStart";
|
|
9920
|
+
IOperateType["drawEnd"] = "drawEnd";
|
|
9921
|
+
IOperateType["drawing"] = "drawing";
|
|
9922
|
+
IOperateType["moving"] = "moving";
|
|
9923
|
+
IOperateType["moveStart"] = "moveStart";
|
|
9924
|
+
IOperateType["moveEnd"] = "moveEnd";
|
|
9925
|
+
IOperateType["brushClear"] = "brushClear";
|
|
9926
|
+
})(exports.IOperateType || (exports.IOperateType = {}));
|
|
9927
|
+
|
|
8918
9928
|
const DEFAULT_BRUSH_ATTRIBUTES = {
|
|
8919
9929
|
brushMode: 'single',
|
|
8920
9930
|
brushType: 'rect',
|
|
@@ -8935,6 +9945,7 @@
|
|
|
8935
9945
|
x2: Infinity
|
|
8936
9946
|
}
|
|
8937
9947
|
};
|
|
9948
|
+
const DEFAULT_SIZE_THRESHOLD = 5;
|
|
8938
9949
|
|
|
8939
9950
|
const delayMap = {
|
|
8940
9951
|
debounce: vutils.debounce,
|
|
@@ -8946,6 +9957,7 @@
|
|
|
8946
9957
|
_container;
|
|
8947
9958
|
_activeDrawState = false;
|
|
8948
9959
|
_cacheDrawPoints = [];
|
|
9960
|
+
_isDrawedBeforeEnd = false;
|
|
8949
9961
|
_activeMoveState = false;
|
|
8950
9962
|
_operatingMaskMoveDx = 0;
|
|
8951
9963
|
_operatingMaskMoveDy = 0;
|
|
@@ -9001,36 +10013,41 @@
|
|
|
9001
10013
|
this._activeMoveState && this._moving(e);
|
|
9002
10014
|
};
|
|
9003
10015
|
_onBrushEnd = (e) => {
|
|
9004
|
-
|
|
9005
|
-
|
|
10016
|
+
const { removeOnClick = true } = this.attribute;
|
|
10017
|
+
if (this._activeDrawState && !this._isDrawedBeforeEnd && removeOnClick) {
|
|
10018
|
+
this._container.incrementalClearChild();
|
|
10019
|
+
this._updateDragMaskCallback &&
|
|
10020
|
+
this._updateDragMaskCallback({
|
|
10021
|
+
operateType: exports.IOperateType.brushClear,
|
|
10022
|
+
operateMask: this._operatingMask,
|
|
10023
|
+
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
10024
|
+
});
|
|
10025
|
+
}
|
|
10026
|
+
else if (!this._outOfInteractiveRange(e)) {
|
|
10027
|
+
this._updateDragMaskCallback &&
|
|
10028
|
+
this._updateDragMaskCallback({
|
|
10029
|
+
operateType: this._activeDrawState ? exports.IOperateType.drawEnd : exports.IOperateType.moveEnd,
|
|
10030
|
+
operateMask: this._operatingMask,
|
|
10031
|
+
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
10032
|
+
});
|
|
9006
10033
|
}
|
|
9007
|
-
this._updateDragMaskCallback &&
|
|
9008
|
-
this._updateDragMaskCallback({
|
|
9009
|
-
operateType: this._activeDrawState ? 'brushEnd' : 'brushMaskUp',
|
|
9010
|
-
operateMask: this._operatingMask,
|
|
9011
|
-
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
9012
|
-
});
|
|
9013
10034
|
this._activeDrawState = false;
|
|
9014
10035
|
this._activeMoveState = false;
|
|
9015
|
-
this.
|
|
10036
|
+
this._isDrawedBeforeEnd = false;
|
|
10037
|
+
this._operatingMask?.setAttribute('pickable', false);
|
|
9016
10038
|
};
|
|
9017
10039
|
_initDraw(e) {
|
|
9018
|
-
const { brushMode
|
|
10040
|
+
const { brushMode } = this.attribute;
|
|
9019
10041
|
const pos = this.eventPosToStagePos(e);
|
|
9020
10042
|
this._cacheDrawPoints = [pos];
|
|
9021
|
-
|
|
9022
|
-
|
|
9023
|
-
}
|
|
9024
|
-
if (brushMode === 'single' && removeOnClick) {
|
|
10043
|
+
this._isDrawedBeforeEnd = false;
|
|
10044
|
+
if (brushMode === 'single') {
|
|
9025
10045
|
this._container.incrementalClearChild();
|
|
9026
|
-
this._addBrushMask();
|
|
9027
|
-
}
|
|
9028
|
-
else if (brushMode === 'multiple') {
|
|
9029
|
-
this._addBrushMask();
|
|
9030
10046
|
}
|
|
10047
|
+
this._addBrushMask();
|
|
9031
10048
|
this._updateDragMaskCallback &&
|
|
9032
10049
|
this._updateDragMaskCallback({
|
|
9033
|
-
operateType:
|
|
10050
|
+
operateType: exports.IOperateType.drawStart,
|
|
9034
10051
|
operateMask: this._operatingMask,
|
|
9035
10052
|
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
9036
10053
|
});
|
|
@@ -9051,13 +10068,16 @@
|
|
|
9051
10068
|
this._operatingMask.setAttribute('pickable', true);
|
|
9052
10069
|
this._updateDragMaskCallback &&
|
|
9053
10070
|
this._updateDragMaskCallback({
|
|
9054
|
-
operateType:
|
|
10071
|
+
operateType: exports.IOperateType.moveStart,
|
|
9055
10072
|
operateMask: this._operatingMask,
|
|
9056
10073
|
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
9057
10074
|
});
|
|
9058
10075
|
}
|
|
9059
10076
|
_drawing(e) {
|
|
9060
10077
|
const pos = this.eventPosToStagePos(e);
|
|
10078
|
+
const { x1 = 0, x2 = 0, y1 = 0, y2 = 0 } = this._operatingMask?._AABBBounds;
|
|
10079
|
+
const { sizeThreshold = DEFAULT_SIZE_THRESHOLD } = this.attribute;
|
|
10080
|
+
this._isDrawedBeforeEnd = !!(Math.abs(x2 - x1) > sizeThreshold || Math.abs(y1 - y2) > sizeThreshold);
|
|
9061
10081
|
if (this._cacheDrawPoints.length > 0) {
|
|
9062
10082
|
const lastPos = this._cacheDrawPoints[this._cacheDrawPoints.length - 1];
|
|
9063
10083
|
if (pos.x === lastPos?.x && pos.y === lastPos?.y) {
|
|
@@ -9070,7 +10090,7 @@
|
|
|
9070
10090
|
this._brushMaskAABBBoundsDict[this._operatingMask.name] = this._operatingMask.AABBBounds;
|
|
9071
10091
|
this._updateDragMaskCallback &&
|
|
9072
10092
|
this._updateDragMaskCallback({
|
|
9073
|
-
operateType:
|
|
10093
|
+
operateType: exports.IOperateType.drawing,
|
|
9074
10094
|
operateMask: this._operatingMask,
|
|
9075
10095
|
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
9076
10096
|
});
|
|
@@ -9094,7 +10114,7 @@
|
|
|
9094
10114
|
this._brushMaskAABBBoundsDict[this._operatingMask.name] = this._operatingMask.AABBBounds;
|
|
9095
10115
|
this._updateDragMaskCallback &&
|
|
9096
10116
|
this._updateDragMaskCallback({
|
|
9097
|
-
operateType:
|
|
10117
|
+
operateType: exports.IOperateType.moving,
|
|
9098
10118
|
operateMask: this._operatingMask,
|
|
9099
10119
|
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
9100
10120
|
});
|
|
@@ -9621,9 +10641,11 @@
|
|
|
9621
10641
|
}
|
|
9622
10642
|
}
|
|
9623
10643
|
|
|
9624
|
-
const version = "0.14.0
|
|
10644
|
+
const version = "0.14.0";
|
|
9625
10645
|
|
|
9626
10646
|
exports.AbstractComponent = AbstractComponent;
|
|
10647
|
+
exports.ArcInfo = ArcInfo;
|
|
10648
|
+
exports.ArcLabel = ArcLabel;
|
|
9627
10649
|
exports.BasePlayer = BasePlayer;
|
|
9628
10650
|
exports.Brush = Brush;
|
|
9629
10651
|
exports.CircleAxis = CircleAxis;
|