@visactor/vrender-components 0.13.9-alpha.6 → 0.13.9-alpha.8
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/brush/brush.d.ts +3 -5
- package/cjs/brush/brush.js +16 -23
- package/cjs/brush/brush.js.map +1 -1
- package/cjs/brush/type.d.ts +1 -10
- package/cjs/brush/type.js +1 -7
- 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 +69 -0
- package/cjs/label/arc.js +399 -0
- package/cjs/label/arc.js.map +1 -0
- package/cjs/label/base.d.ts +2 -1
- package/cjs/label/base.js +60 -23
- 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 +0 -2
- package/cjs/label/overlap/bitmap.js.map +1 -1
- package/cjs/label/type.d.ts +41 -1
- 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/tooltip/util.js.map +1 -1
- package/dist/index.js +863 -67
- package/dist/index.min.js +1 -1
- package/es/brush/brush.d.ts +3 -5
- package/es/brush/brush.js +13 -22
- package/es/brush/brush.js.map +1 -1
- package/es/brush/type.d.ts +1 -10
- package/es/brush/type.js +1 -7
- 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 +69 -0
- package/es/label/arc.js +389 -0
- package/es/label/arc.js.map +1 -0
- package/es/label/base.d.ts +2 -1
- package/es/label/base.js +60 -23
- 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 +0 -2
- package/es/label/overlap/bitmap.js.map +1 -1
- package/es/label/type.d.ts +41 -1
- 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/tooltip/util.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1311,9 +1311,6 @@
|
|
|
1311
1311
|
_clear(index >>> DIV, ~(1 << (index & MOD)));
|
|
1312
1312
|
},
|
|
1313
1313
|
getRange: ({ x1, y1, x2, y2 }) => {
|
|
1314
|
-
if (x2 < 0 || y2 < 0 || x1 > w || y1 > h) {
|
|
1315
|
-
return true;
|
|
1316
|
-
}
|
|
1317
1314
|
let r = y2;
|
|
1318
1315
|
let start;
|
|
1319
1316
|
let end;
|
|
@@ -1346,9 +1343,6 @@
|
|
|
1346
1343
|
return false;
|
|
1347
1344
|
},
|
|
1348
1345
|
setRange: ({ x1, y1, x2, y2 }) => {
|
|
1349
|
-
if (x2 < 0 || y2 < 0 || x1 > w || y1 > h) {
|
|
1350
|
-
return;
|
|
1351
|
-
}
|
|
1352
1346
|
let start;
|
|
1353
1347
|
let end;
|
|
1354
1348
|
let indexStart;
|
|
@@ -1598,6 +1592,10 @@
|
|
|
1598
1592
|
_lastHover;
|
|
1599
1593
|
_lastSelect;
|
|
1600
1594
|
_enableAnimation;
|
|
1595
|
+
layoutArcLabels(position, attribute, currentMarks) {
|
|
1596
|
+
const arcs = [];
|
|
1597
|
+
return arcs;
|
|
1598
|
+
}
|
|
1601
1599
|
render() {
|
|
1602
1600
|
this._prepare();
|
|
1603
1601
|
const { overlap, smartInvert, dataFilter, customLayoutFunc, customOverlapFunc } = this.attribute;
|
|
@@ -1615,7 +1613,7 @@
|
|
|
1615
1613
|
labels = customOverlapFunc(labels, (d) => this._idToGraphic.get(d.id));
|
|
1616
1614
|
}
|
|
1617
1615
|
else {
|
|
1618
|
-
if (overlap !== false) {
|
|
1616
|
+
if (overlap !== false && this.attribute.type !== 'arc') {
|
|
1619
1617
|
labels = this._overlapping(labels);
|
|
1620
1618
|
}
|
|
1621
1619
|
}
|
|
@@ -1737,20 +1735,45 @@
|
|
|
1737
1735
|
const textData = data[i];
|
|
1738
1736
|
const baseMark = this._idToGraphic.get(textData.id);
|
|
1739
1737
|
const labelAttribute = {
|
|
1738
|
+
fill: baseMark.attribute.fill,
|
|
1740
1739
|
...textStyle,
|
|
1741
1740
|
...textData
|
|
1742
1741
|
};
|
|
1743
1742
|
const text = this._createLabelText(labelAttribute);
|
|
1744
1743
|
const textBounds = this.getGraphicBounds(text);
|
|
1745
1744
|
const graphicBounds = this.getGraphicBounds(baseMark, { x: textData.x, y: textData.y });
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1745
|
+
if (this.attribute.type === 'arc') {
|
|
1746
|
+
const graphicAttributes = baseMark.attribute;
|
|
1747
|
+
const { width, height } = this.attribute;
|
|
1748
|
+
this.labeling(textBounds, graphicBounds, vutils.isFunction(position) ? position(textData) : position, offset, graphicAttributes, textData, width, height, this.attribute);
|
|
1749
|
+
labels.push(text);
|
|
1750
|
+
}
|
|
1751
|
+
else {
|
|
1752
|
+
const textLocation = this.labeling(textBounds, graphicBounds, vutils.isFunction(position) ? position(textData) : position, offset);
|
|
1753
|
+
if (!textLocation) {
|
|
1754
|
+
continue;
|
|
1755
|
+
}
|
|
1756
|
+
labelAttribute.x = textLocation.x;
|
|
1757
|
+
labelAttribute.y = textLocation.y;
|
|
1758
|
+
text.setAttributes(textLocation);
|
|
1759
|
+
labels.push(text);
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
if (this.attribute.type === 'arc') {
|
|
1763
|
+
const arcs = this.layoutArcLabels(position, this.attribute, Array.from(this._idToGraphic.values()));
|
|
1764
|
+
for (let i = 0; i < data.length; i++) {
|
|
1765
|
+
const textData = data[i];
|
|
1766
|
+
const basedArc = arcs.find(arc => arc.labelText === textData.text);
|
|
1767
|
+
const labelAttribute = {
|
|
1768
|
+
x: basedArc.labelPosition.x,
|
|
1769
|
+
y: basedArc.labelPosition.y,
|
|
1770
|
+
angle: this.attribute.angle ?? basedArc.angle
|
|
1771
|
+
};
|
|
1772
|
+
labels[i].setAttributes(labelAttribute);
|
|
1773
|
+
labels[i].pointA = basedArc.pointA;
|
|
1774
|
+
labels[i].pointB = basedArc.pointB;
|
|
1775
|
+
labels[i].pointC = basedArc.pointC;
|
|
1749
1776
|
}
|
|
1750
|
-
labelAttribute.x = textLocation.x;
|
|
1751
|
-
labelAttribute.y = textLocation.y;
|
|
1752
|
-
text.setAttributes(textLocation);
|
|
1753
|
-
labels.push(text);
|
|
1754
1777
|
}
|
|
1755
1778
|
return labels;
|
|
1756
1779
|
}
|
|
@@ -1796,15 +1819,6 @@
|
|
|
1796
1819
|
continue;
|
|
1797
1820
|
}
|
|
1798
1821
|
}
|
|
1799
|
-
let hasPlace = false;
|
|
1800
|
-
for (let j = 0; j < strategy.length; j++) {
|
|
1801
|
-
hasPlace = place(bmpTool, bitmap, strategy[j], this.attribute, text, this.getGraphicBounds(baseMark, labels[i]), this.labeling);
|
|
1802
|
-
if (hasPlace !== false) {
|
|
1803
|
-
text.setAttributes({ x: hasPlace.x, y: hasPlace.y });
|
|
1804
|
-
result.push(text);
|
|
1805
|
-
break;
|
|
1806
|
-
}
|
|
1807
|
-
}
|
|
1808
1822
|
if (clampForce) {
|
|
1809
1823
|
const { dx = 0, dy = 0 } = clampText(text, bmpTool.width, bmpTool.height);
|
|
1810
1824
|
if (!(dx === 0 && dy === 0) &&
|
|
@@ -1815,11 +1829,19 @@
|
|
|
1815
1829
|
y2: text.AABBBounds.y2 + dy
|
|
1816
1830
|
})) {
|
|
1817
1831
|
text.setAttributes({ x: text.attribute.x + dx, y: text.attribute.y + dy });
|
|
1818
|
-
bitmap.setRange(boundToRange(bmpTool, text.AABBBounds, true));
|
|
1819
1832
|
result.push(text);
|
|
1820
1833
|
continue;
|
|
1821
1834
|
}
|
|
1822
1835
|
}
|
|
1836
|
+
let hasPlace = false;
|
|
1837
|
+
for (let j = 0; j < strategy.length; j++) {
|
|
1838
|
+
hasPlace = place(bmpTool, bitmap, strategy[j], this.attribute, text, this.getGraphicBounds(baseMark, labels[i]), this.labeling);
|
|
1839
|
+
if (hasPlace !== false) {
|
|
1840
|
+
text.setAttributes({ x: hasPlace.x, y: hasPlace.y });
|
|
1841
|
+
result.push(text);
|
|
1842
|
+
break;
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1823
1845
|
!hasPlace && !hideOnHit && result.push(text);
|
|
1824
1846
|
}
|
|
1825
1847
|
if (vutils.isFunction(this.onAfterLabelOverlap)) {
|
|
@@ -1861,14 +1883,29 @@
|
|
|
1861
1883
|
const prevTextMap = this._graphicToText || new Map();
|
|
1862
1884
|
const texts = [];
|
|
1863
1885
|
labels.forEach((text, index) => {
|
|
1886
|
+
let labelLine;
|
|
1887
|
+
if (this.attribute.type === 'arc' && this.attribute.position === 'outside') {
|
|
1888
|
+
labelLine = vrender.createPath({
|
|
1889
|
+
visible: text.attribute?.visible ?? true,
|
|
1890
|
+
stroke: text.attribute?.line?.stroke ?? text.attribute?.fill,
|
|
1891
|
+
lineWidth: 1,
|
|
1892
|
+
path: `M${Math.round(text.pointA.x)},${Math.round(text.pointA.y)}` +
|
|
1893
|
+
` L${Math.round(text.pointB.x)},${Math.round(text.pointB.y)}` +
|
|
1894
|
+
` L${Math.round(text.pointC.x)},${Math.round(text.pointC.y)}`
|
|
1895
|
+
});
|
|
1896
|
+
}
|
|
1864
1897
|
const relatedGraphic = this._idToGraphic.get(text.attribute.id);
|
|
1865
1898
|
const state = prevTextMap?.get(relatedGraphic) ? 'update' : 'enter';
|
|
1866
1899
|
if (state === 'enter') {
|
|
1867
1900
|
texts.push(text);
|
|
1901
|
+
if (this.attribute.type === 'arc' && this.attribute.position === 'outside') ;
|
|
1868
1902
|
currentTextMap.set(relatedGraphic, text);
|
|
1869
1903
|
if (!disableAnimation && relatedGraphic) {
|
|
1870
1904
|
const { from, to } = getAnimationAttributes(text.attribute, 'fadeIn');
|
|
1871
1905
|
this.add(text);
|
|
1906
|
+
if (this.attribute.type === 'arc' && this.attribute.position === 'outside') {
|
|
1907
|
+
this.add(labelLine);
|
|
1908
|
+
}
|
|
1872
1909
|
relatedGraphic.onAnimateBind = () => {
|
|
1873
1910
|
text.setAttributes(from);
|
|
1874
1911
|
const listener = this._afterRelatedGraphicAttributeUpdate(text, texts, index, relatedGraphic, {
|
|
@@ -1883,6 +1920,9 @@
|
|
|
1883
1920
|
}
|
|
1884
1921
|
else {
|
|
1885
1922
|
this.add(text);
|
|
1923
|
+
if (this.attribute.type === 'arc' && this.attribute.position === 'outside') {
|
|
1924
|
+
this.add(labelLine);
|
|
1925
|
+
}
|
|
1886
1926
|
}
|
|
1887
1927
|
}
|
|
1888
1928
|
if (state === 'update') {
|
|
@@ -1976,7 +2016,15 @@
|
|
|
1976
2016
|
continue;
|
|
1977
2017
|
}
|
|
1978
2018
|
const baseMark = this._idToGraphic.get(label.attribute.id);
|
|
1979
|
-
|
|
2019
|
+
let isInside = canPlaceInside(label.AABBBounds, baseMark?.AABBBounds);
|
|
2020
|
+
if (this.attribute.type === 'arc') {
|
|
2021
|
+
if (this.attribute.position === 'inside') {
|
|
2022
|
+
isInside = true;
|
|
2023
|
+
}
|
|
2024
|
+
else {
|
|
2025
|
+
isInside = false;
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
1980
2028
|
if (label.attribute.stroke && label.attribute.lineWidth > 0) {
|
|
1981
2029
|
label.setAttributes({
|
|
1982
2030
|
fill: labelSmartInvert(label.attribute.fill, label.attribute.stroke, textType, contrastRatiosThreshold, alternativeColors)
|
|
@@ -2203,9 +2251,774 @@
|
|
|
2203
2251
|
}
|
|
2204
2252
|
}
|
|
2205
2253
|
|
|
2254
|
+
function polarToCartesian(point) {
|
|
2255
|
+
if (!point.radius) {
|
|
2256
|
+
return { x: 0, y: 0 };
|
|
2257
|
+
}
|
|
2258
|
+
return {
|
|
2259
|
+
x: Math.cos(point.angle) * point.radius,
|
|
2260
|
+
y: Math.sin(point.angle) * point.radius
|
|
2261
|
+
};
|
|
2262
|
+
}
|
|
2263
|
+
function circlePoint(x0, y0, radius, radian) {
|
|
2264
|
+
const offset = polarToCartesian({
|
|
2265
|
+
radius,
|
|
2266
|
+
angle: radian
|
|
2267
|
+
});
|
|
2268
|
+
return {
|
|
2269
|
+
x: x0 + offset.x,
|
|
2270
|
+
y: y0 + offset.y
|
|
2271
|
+
};
|
|
2272
|
+
}
|
|
2273
|
+
function computeQuadrant(angle) {
|
|
2274
|
+
angle = normalizeAngle(angle);
|
|
2275
|
+
if (angle > 0 && angle <= Math.PI / 2) {
|
|
2276
|
+
return 2;
|
|
2277
|
+
}
|
|
2278
|
+
else if (angle > Math.PI / 2 && angle <= Math.PI) {
|
|
2279
|
+
return 3;
|
|
2280
|
+
}
|
|
2281
|
+
else if (angle > Math.PI && angle <= (3 * Math.PI) / 2) {
|
|
2282
|
+
return 4;
|
|
2283
|
+
}
|
|
2284
|
+
return 1;
|
|
2285
|
+
}
|
|
2286
|
+
function normalizeAngle(angle) {
|
|
2287
|
+
while (angle < 0) {
|
|
2288
|
+
angle += Math.PI * 2;
|
|
2289
|
+
}
|
|
2290
|
+
while (angle >= Math.PI * 2) {
|
|
2291
|
+
angle -= Math.PI * 2;
|
|
2292
|
+
}
|
|
2293
|
+
return angle;
|
|
2294
|
+
}
|
|
2295
|
+
function isQuadrantLeft(quadrant) {
|
|
2296
|
+
return quadrant === 3 || quadrant === 4;
|
|
2297
|
+
}
|
|
2298
|
+
function isQuadrantRight(quadrant) {
|
|
2299
|
+
return quadrant === 1 || quadrant === 2;
|
|
2300
|
+
}
|
|
2301
|
+
function lineCirclePoints(a, b, c, x0, y0, r) {
|
|
2302
|
+
if ((a === 0 && b === 0) || r <= 0) {
|
|
2303
|
+
return [];
|
|
2304
|
+
}
|
|
2305
|
+
if (a === 0) {
|
|
2306
|
+
const y1 = -c / b;
|
|
2307
|
+
const fy = (y1 - y0) ** 2;
|
|
2308
|
+
const fd = r ** 2 - fy;
|
|
2309
|
+
if (fd < 0) {
|
|
2310
|
+
return [];
|
|
2311
|
+
}
|
|
2312
|
+
else if (fd === 0) {
|
|
2313
|
+
return [{ x: x0, y: y1 }];
|
|
2314
|
+
}
|
|
2315
|
+
const x1 = Math.sqrt(fd) + x0;
|
|
2316
|
+
const x2 = -Math.sqrt(fd) + x0;
|
|
2317
|
+
return [
|
|
2318
|
+
{ x: x1, y: y1 },
|
|
2319
|
+
{ x: x2, y: y1 }
|
|
2320
|
+
];
|
|
2321
|
+
}
|
|
2322
|
+
else if (b === 0) {
|
|
2323
|
+
const x1 = -c / a;
|
|
2324
|
+
const fx = (x1 - x0) ** 2;
|
|
2325
|
+
const fd = r ** 2 - fx;
|
|
2326
|
+
if (fd < 0) {
|
|
2327
|
+
return [];
|
|
2328
|
+
}
|
|
2329
|
+
else if (fd === 0) {
|
|
2330
|
+
return [{ x: x1, y: y0 }];
|
|
2331
|
+
}
|
|
2332
|
+
const y1 = Math.sqrt(fd) + y0;
|
|
2333
|
+
const y2 = -Math.sqrt(fd) + y0;
|
|
2334
|
+
return [
|
|
2335
|
+
{ x: x1, y: y1 },
|
|
2336
|
+
{ x: x1, y: y2 }
|
|
2337
|
+
];
|
|
2338
|
+
}
|
|
2339
|
+
const fa = (b / a) ** 2 + 1;
|
|
2340
|
+
const fb = 2 * ((c / a + x0) * (b / a) - y0);
|
|
2341
|
+
const fc = (c / a + x0) ** 2 + y0 ** 2 - r ** 2;
|
|
2342
|
+
const fd = fb ** 2 - 4 * fa * fc;
|
|
2343
|
+
if (fd < 0) {
|
|
2344
|
+
return [];
|
|
2345
|
+
}
|
|
2346
|
+
const y1 = (-fb + Math.sqrt(fd)) / (2 * fa);
|
|
2347
|
+
const y2 = (-fb - Math.sqrt(fd)) / (2 * fa);
|
|
2348
|
+
const x1 = -(b * y1 + c) / a;
|
|
2349
|
+
const x2 = -(b * y2 + c) / a;
|
|
2350
|
+
if (fd === 0) {
|
|
2351
|
+
return [{ x: x1, y: y1 }];
|
|
2352
|
+
}
|
|
2353
|
+
return [
|
|
2354
|
+
{ x: x1, y: y1 },
|
|
2355
|
+
{ x: x2, y: y2 }
|
|
2356
|
+
];
|
|
2357
|
+
}
|
|
2358
|
+
function connectLineRadian(radius, length) {
|
|
2359
|
+
if (length > radius * 2) {
|
|
2360
|
+
return NaN;
|
|
2361
|
+
}
|
|
2362
|
+
return Math.asin(length / 2 / radius) * 2;
|
|
2363
|
+
}
|
|
2364
|
+
function checkBoundsOverlap(boundsA, boundsB) {
|
|
2365
|
+
const { x1: ax1, y1: ay1, x2: ax2, y2: ay2 } = boundsA;
|
|
2366
|
+
const { x1: bx1, y1: by1, x2: bx2, y2: by2 } = boundsB;
|
|
2367
|
+
return !((ax1 <= bx1 && ax2 <= bx1) ||
|
|
2368
|
+
(ax1 >= bx2 && ax2 >= bx2) ||
|
|
2369
|
+
(ay1 <= by1 && ay2 <= by1) ||
|
|
2370
|
+
(ay1 >= by2 && ay2 >= by2));
|
|
2371
|
+
}
|
|
2372
|
+
|
|
2373
|
+
class ArcInfo {
|
|
2374
|
+
key;
|
|
2375
|
+
refDatum;
|
|
2376
|
+
center;
|
|
2377
|
+
outerCenter;
|
|
2378
|
+
labelSize;
|
|
2379
|
+
labelPosition;
|
|
2380
|
+
labelLimit;
|
|
2381
|
+
labelVisible;
|
|
2382
|
+
lastLabelY;
|
|
2383
|
+
labelYRange;
|
|
2384
|
+
labelText;
|
|
2385
|
+
pointA;
|
|
2386
|
+
pointB;
|
|
2387
|
+
pointC;
|
|
2388
|
+
quadrant;
|
|
2389
|
+
radian;
|
|
2390
|
+
middleAngle;
|
|
2391
|
+
k;
|
|
2392
|
+
textAlign;
|
|
2393
|
+
textBaseline;
|
|
2394
|
+
angle;
|
|
2395
|
+
constructor(refDatum, center, outerCenter, quadrant, radian, middleAngle) {
|
|
2396
|
+
this.refDatum = refDatum;
|
|
2397
|
+
this.center = center;
|
|
2398
|
+
this.outerCenter = outerCenter;
|
|
2399
|
+
this.quadrant = quadrant;
|
|
2400
|
+
this.radian = radian;
|
|
2401
|
+
this.middleAngle = middleAngle;
|
|
2402
|
+
this.labelVisible = true;
|
|
2403
|
+
this.labelLimit = 0;
|
|
2404
|
+
}
|
|
2405
|
+
getLabelBounds() {
|
|
2406
|
+
if (!this.labelPosition || !this.labelSize) {
|
|
2407
|
+
return { x1: 0, x2: 0, y1: 0, y2: 0 };
|
|
2408
|
+
}
|
|
2409
|
+
return {
|
|
2410
|
+
x1: this.labelPosition.x - this.labelSize.width / 2,
|
|
2411
|
+
y1: this.labelPosition.y - this.labelSize.height / 2,
|
|
2412
|
+
x2: this.labelPosition.x + this.labelSize.width / 2,
|
|
2413
|
+
y2: this.labelPosition.y + this.labelSize.height / 2
|
|
2414
|
+
};
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
class ArcLabel extends LabelBase {
|
|
2418
|
+
name = 'arc-label';
|
|
2419
|
+
static defaultAttributes = {
|
|
2420
|
+
coverEnable: false,
|
|
2421
|
+
spaceWidth: 5,
|
|
2422
|
+
layoutArcGap: 6,
|
|
2423
|
+
textStyle: {
|
|
2424
|
+
visible: true,
|
|
2425
|
+
fontSize: 14,
|
|
2426
|
+
fontWeight: 'normal',
|
|
2427
|
+
fillOpacity: 1,
|
|
2428
|
+
textAlign: 'center',
|
|
2429
|
+
textBaseline: 'middle'
|
|
2430
|
+
},
|
|
2431
|
+
position: 'outside',
|
|
2432
|
+
offset: 0,
|
|
2433
|
+
line: {
|
|
2434
|
+
visible: true,
|
|
2435
|
+
line1MinLength: 20,
|
|
2436
|
+
line2MinLength: 10
|
|
2437
|
+
},
|
|
2438
|
+
layout: {
|
|
2439
|
+
align: 'arc',
|
|
2440
|
+
strategy: 'priority',
|
|
2441
|
+
tangentConstraint: true
|
|
2442
|
+
}
|
|
2443
|
+
};
|
|
2444
|
+
_ellipsisWidth = 0;
|
|
2445
|
+
_arcLeft = new Map();
|
|
2446
|
+
_arcRight = new Map();
|
|
2447
|
+
constructor(attributes) {
|
|
2448
|
+
super(vutils.merge({}, ArcLabel.defaultAttributes, attributes));
|
|
2449
|
+
}
|
|
2450
|
+
labeling(textBounds, graphicBounds, position = 'outside', offset = 0, graphicAttributes, textData, width, height, attribute) {
|
|
2451
|
+
if (!textBounds || !graphicBounds) {
|
|
2452
|
+
return;
|
|
2453
|
+
}
|
|
2454
|
+
const radiusRatio = this.computeLayoutOuterRadius(graphicAttributes.outerRadius, width, height);
|
|
2455
|
+
const radius = this.computeRadius(radiusRatio, width, height);
|
|
2456
|
+
const center = { x: graphicAttributes?.x ?? 0, y: graphicAttributes?.y ?? 0 };
|
|
2457
|
+
const item = textData;
|
|
2458
|
+
const arcMiddleAngle = (graphicAttributes.startAngle + graphicAttributes.endAngle) / 2;
|
|
2459
|
+
const intervalAngle = graphicAttributes.endAngle - graphicAttributes.startAngle;
|
|
2460
|
+
const arcQuadrant = computeQuadrant(graphicAttributes.endAngle - intervalAngle / 2);
|
|
2461
|
+
const arcMiddle = circlePoint(center.x, center.y, graphicAttributes.outerRadius, arcMiddleAngle);
|
|
2462
|
+
const outerArcMiddle = circlePoint(center.x, center.y, radius + attribute.line.line1MinLength, arcMiddleAngle);
|
|
2463
|
+
const arc = new ArcInfo(item, arcMiddle, outerArcMiddle, arcQuadrant, intervalAngle, arcMiddleAngle);
|
|
2464
|
+
arc.pointA = circlePoint(center.x, center.y, this.computeDatumRadius(center.x * 2, center.y * 2, graphicAttributes.outerRadius), arc.middleAngle);
|
|
2465
|
+
arc.labelSize = {
|
|
2466
|
+
width: textBounds.x2 - textBounds.x1,
|
|
2467
|
+
height: textBounds.y2 - textBounds.y1
|
|
2468
|
+
};
|
|
2469
|
+
if (isQuadrantRight(arc.quadrant)) {
|
|
2470
|
+
arc.textAlign = 'left';
|
|
2471
|
+
arc.textBaseline = 'middle';
|
|
2472
|
+
this._arcRight.set(arc.refDatum, arc);
|
|
2473
|
+
}
|
|
2474
|
+
else if (isQuadrantLeft(arc.quadrant)) {
|
|
2475
|
+
arc.textAlign = 'right';
|
|
2476
|
+
arc.textBaseline = 'middle';
|
|
2477
|
+
this._arcLeft.set(arc.refDatum, arc);
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
layoutArcLabels(position, attribute, currentMarks) {
|
|
2481
|
+
const leftArcs = Array.from(this._arcLeft.values());
|
|
2482
|
+
const rightArcs = Array.from(this._arcRight.values());
|
|
2483
|
+
const arcs = [];
|
|
2484
|
+
if (position === 'inside') {
|
|
2485
|
+
arcs.push(...this._layoutInsideLabels(rightArcs, attribute, currentMarks));
|
|
2486
|
+
arcs.push(...this._layoutInsideLabels(leftArcs, attribute, currentMarks));
|
|
2487
|
+
}
|
|
2488
|
+
else {
|
|
2489
|
+
arcs.push(...this._layoutOutsideLabels(rightArcs, attribute, currentMarks));
|
|
2490
|
+
arcs.push(...this._layoutOutsideLabels(leftArcs, attribute, currentMarks));
|
|
2491
|
+
}
|
|
2492
|
+
return arcs;
|
|
2493
|
+
}
|
|
2494
|
+
_layoutInsideLabels(arcs, attribute, currentMarks) {
|
|
2495
|
+
const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
|
|
2496
|
+
const innerRadiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.innerRadius, attribute.width, attribute.height);
|
|
2497
|
+
const outerRadiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
|
|
2498
|
+
const labelConfig = attribute;
|
|
2499
|
+
const spaceWidth = labelConfig.spaceWidth;
|
|
2500
|
+
arcs.forEach((arc) => {
|
|
2501
|
+
const { labelSize, radian } = arc;
|
|
2502
|
+
const innerRadius = this.computeRadius(innerRadiusRatio, attribute.width, attribute.height, 1);
|
|
2503
|
+
const outerRadius = this.computeRadius(outerRadiusRatio, attribute.width, attribute.height, 1);
|
|
2504
|
+
const minRadian = connectLineRadian(outerRadius, labelSize.height);
|
|
2505
|
+
let limit;
|
|
2506
|
+
if (radian < minRadian) {
|
|
2507
|
+
limit = 0;
|
|
2508
|
+
}
|
|
2509
|
+
else {
|
|
2510
|
+
let minRadius;
|
|
2511
|
+
if (radian >= Math.PI) {
|
|
2512
|
+
minRadius = innerRadius;
|
|
2513
|
+
}
|
|
2514
|
+
else {
|
|
2515
|
+
minRadius = Math.max(innerRadius, labelSize.height / 2 / Math.tan(radian / 2));
|
|
2516
|
+
}
|
|
2517
|
+
limit = outerRadius - minRadius - spaceWidth;
|
|
2518
|
+
}
|
|
2519
|
+
if (labelConfig?.rotate !== true) {
|
|
2520
|
+
limit = outerRadius - spaceWidth;
|
|
2521
|
+
}
|
|
2522
|
+
const text = this._getFormatLabelText(arc.refDatum, limit);
|
|
2523
|
+
arc.labelText = text;
|
|
2524
|
+
const labelWidth = Math.min(limit, arc.labelSize.width);
|
|
2525
|
+
const align = this._computeAlign(arc, attribute);
|
|
2526
|
+
const alignOffset = align === 'left' ? labelWidth : align === 'right' ? 0 : labelWidth / 2;
|
|
2527
|
+
const labelRadius = outerRadius - spaceWidth - alignOffset;
|
|
2528
|
+
arc.labelPosition = circlePoint(center.x, center.y, labelRadius, arc.middleAngle);
|
|
2529
|
+
arc.labelLimit = labelWidth;
|
|
2530
|
+
if (!vutils.isGreater(labelWidth, 0)) {
|
|
2531
|
+
arc.labelVisible = false;
|
|
2532
|
+
}
|
|
2533
|
+
(arc.textAlign = 'center'), (arc.textBaseline = 'middle');
|
|
2534
|
+
arc.angle = arc.middleAngle;
|
|
2535
|
+
});
|
|
2536
|
+
return arcs;
|
|
2537
|
+
}
|
|
2538
|
+
_layoutOutsideLabels(arcs, attribute, currentMarks) {
|
|
2539
|
+
const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
|
|
2540
|
+
const height = center.y * 2;
|
|
2541
|
+
const line2MinLength = attribute.line.line2MinLength;
|
|
2542
|
+
const labelLayout = attribute.layout;
|
|
2543
|
+
const spaceWidth = attribute.spaceWidth;
|
|
2544
|
+
arcs.forEach(arc => {
|
|
2545
|
+
const direction = isQuadrantLeft(arc.quadrant) ? -1 : 1;
|
|
2546
|
+
arc.labelPosition = {
|
|
2547
|
+
x: arc.outerCenter.x + direction * (arc.labelSize.width / 2 + line2MinLength + spaceWidth),
|
|
2548
|
+
y: arc.outerCenter.y
|
|
2549
|
+
};
|
|
2550
|
+
});
|
|
2551
|
+
arcs.sort((a, b) => {
|
|
2552
|
+
return a.labelPosition.y - b.labelPosition.y;
|
|
2553
|
+
});
|
|
2554
|
+
if (attribute.coverEnable !== false || labelLayout.strategy === 'none') {
|
|
2555
|
+
for (const arc of arcs) {
|
|
2556
|
+
const { labelPosition, labelSize } = arc;
|
|
2557
|
+
arc.labelLimit = labelSize.width;
|
|
2558
|
+
arc.pointB = isQuadrantLeft(arc.quadrant)
|
|
2559
|
+
? {
|
|
2560
|
+
x: labelPosition.x + labelSize.width / 2 + line2MinLength + spaceWidth,
|
|
2561
|
+
y: labelPosition.y
|
|
2562
|
+
}
|
|
2563
|
+
: {
|
|
2564
|
+
x: labelPosition.x - labelSize.width / 2 - line2MinLength - spaceWidth,
|
|
2565
|
+
y: labelPosition.y
|
|
2566
|
+
};
|
|
2567
|
+
this._computeX(arc, attribute, currentMarks);
|
|
2568
|
+
}
|
|
2569
|
+
if (attribute.coverEnable === false && labelLayout.strategy === 'none') {
|
|
2570
|
+
this._coverLabels(arcs);
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
else {
|
|
2574
|
+
const maxLabels = height / (attribute.textStyle?.fontSize || 16);
|
|
2575
|
+
this._adjustY(arcs, maxLabels, attribute, currentMarks);
|
|
2576
|
+
const { minY, maxY } = arcs.reduce((yInfo, arc) => {
|
|
2577
|
+
const { y1, y2 } = arc.getLabelBounds();
|
|
2578
|
+
yInfo.minY = Math.max(0, Math.min(y1, yInfo.minY));
|
|
2579
|
+
yInfo.maxY = Math.min(height, Math.max(y2, yInfo.maxY));
|
|
2580
|
+
return yInfo;
|
|
2581
|
+
}, { minY: Infinity, maxY: -Infinity });
|
|
2582
|
+
const halfY = Math.max(Math.abs(height / 2 - minY), Math.abs(maxY - height / 2));
|
|
2583
|
+
const r = this._computeLayoutRadius(halfY, attribute, currentMarks);
|
|
2584
|
+
for (const arc of arcs) {
|
|
2585
|
+
this._computePointB(arc, r, attribute, currentMarks);
|
|
2586
|
+
this._computeX(arc, attribute, currentMarks);
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
const width = center.x * 2;
|
|
2590
|
+
arcs.forEach(arc => {
|
|
2591
|
+
if (arc.labelVisible &&
|
|
2592
|
+
(vutils.isLess(arc.pointB.x, line2MinLength + spaceWidth) ||
|
|
2593
|
+
vutils.isGreater(arc.pointB.x, width - line2MinLength - spaceWidth))) {
|
|
2594
|
+
arc.labelVisible = false;
|
|
2595
|
+
}
|
|
2596
|
+
arc.angle = 0;
|
|
2597
|
+
arc.labelPosition.x = isQuadrantLeft(arc.quadrant)
|
|
2598
|
+
? arc.labelPosition.x
|
|
2599
|
+
: arc.labelPosition.x + 0.5 * arc.labelSize.width;
|
|
2600
|
+
});
|
|
2601
|
+
return arcs;
|
|
2602
|
+
}
|
|
2603
|
+
_computeX(arc, attribute, currentMarks) {
|
|
2604
|
+
const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
|
|
2605
|
+
const plotLayout = { width: center.x * 2, height: center.y * 2 };
|
|
2606
|
+
const radiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
|
|
2607
|
+
const line1MinLength = attribute.line.line1MinLength;
|
|
2608
|
+
const line2MinLength = attribute.line.line2MinLength;
|
|
2609
|
+
const labelLayoutAlign = attribute.layout?.align;
|
|
2610
|
+
const spaceWidth = attribute.spaceWidth;
|
|
2611
|
+
const align = this._computeAlign(arc, attribute);
|
|
2612
|
+
const { labelPosition, quadrant, pointB } = arc;
|
|
2613
|
+
if (!vutils.isValidNumber(pointB.x * pointB.y)) {
|
|
2614
|
+
arc.pointC = { x: NaN, y: NaN };
|
|
2615
|
+
labelPosition.x = NaN;
|
|
2616
|
+
arc.labelLimit = 0;
|
|
2617
|
+
}
|
|
2618
|
+
const radius = this.computeRadius(radiusRatio, attribute.width, attribute.height);
|
|
2619
|
+
const flag = isQuadrantLeft(quadrant) ? -1 : 1;
|
|
2620
|
+
let cx = 0;
|
|
2621
|
+
const restWidth = flag > 0 ? plotLayout.width - pointB.x : pointB.x;
|
|
2622
|
+
let limit = restWidth - line2MinLength - spaceWidth;
|
|
2623
|
+
if (labelLayoutAlign === 'labelLine') {
|
|
2624
|
+
cx = (radius + line1MinLength + line2MinLength) * flag + center.x;
|
|
2625
|
+
limit = (flag > 0 ? plotLayout.width - cx : cx) - spaceWidth;
|
|
2626
|
+
}
|
|
2627
|
+
const text = this._getFormatLabelText(arc.refDatum, limit);
|
|
2628
|
+
arc.labelText = text;
|
|
2629
|
+
let labelWidth = Math.min(limit, arc.labelSize.width);
|
|
2630
|
+
switch (labelLayoutAlign) {
|
|
2631
|
+
case 'labelLine':
|
|
2632
|
+
break;
|
|
2633
|
+
case 'edge':
|
|
2634
|
+
cx = flag > 0 ? plotLayout.width - labelWidth - spaceWidth : labelWidth + spaceWidth;
|
|
2635
|
+
break;
|
|
2636
|
+
case 'arc':
|
|
2637
|
+
default:
|
|
2638
|
+
cx = pointB.x + flag * line2MinLength;
|
|
2639
|
+
break;
|
|
2640
|
+
}
|
|
2641
|
+
labelWidth = Math.max(this._ellipsisWidth, labelWidth);
|
|
2642
|
+
arc.pointC = { x: cx, y: labelPosition.y };
|
|
2643
|
+
if (labelLayoutAlign === 'edge') {
|
|
2644
|
+
const alignOffset = this._computeAlignOffset(align, labelWidth, -flag);
|
|
2645
|
+
labelPosition.x = flag > 0 ? plotLayout.width + alignOffset : alignOffset;
|
|
2646
|
+
}
|
|
2647
|
+
else {
|
|
2648
|
+
const alignOffset = this._computeAlignOffset(align, labelWidth, flag);
|
|
2649
|
+
labelPosition.x = cx + alignOffset + flag * spaceWidth;
|
|
2650
|
+
}
|
|
2651
|
+
arc.labelLimit = labelWidth;
|
|
2652
|
+
}
|
|
2653
|
+
_computeAlignOffset(align, labelWidth, alignFlag) {
|
|
2654
|
+
switch (align) {
|
|
2655
|
+
case 'left':
|
|
2656
|
+
return alignFlag < 0 ? -labelWidth : 0;
|
|
2657
|
+
case 'right':
|
|
2658
|
+
return alignFlag < 0 ? 0 : labelWidth;
|
|
2659
|
+
case 'center':
|
|
2660
|
+
default:
|
|
2661
|
+
return (labelWidth / 2) * alignFlag;
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
_computeAlign(arc, attribute) {
|
|
2665
|
+
const labelConfig = attribute;
|
|
2666
|
+
const textAlign = labelConfig.textStyle?.textAlign ?? labelConfig.textStyle?.align;
|
|
2667
|
+
const layoutAlign = labelConfig.layout?.textAlign ?? labelConfig.layout?.align;
|
|
2668
|
+
if (labelConfig.position !== 'inside') {
|
|
2669
|
+
if (vutils.isNil(textAlign) || textAlign === 'auto') {
|
|
2670
|
+
if (layoutAlign === 'edge') {
|
|
2671
|
+
return isQuadrantLeft(arc.quadrant) ? 'left' : 'right';
|
|
2672
|
+
}
|
|
2673
|
+
return isQuadrantLeft(arc.quadrant) ? 'right' : 'left';
|
|
2674
|
+
}
|
|
2675
|
+
return textAlign;
|
|
2676
|
+
}
|
|
2677
|
+
return vutils.isNil(textAlign) || textAlign === 'auto' ? 'center' : textAlign;
|
|
2678
|
+
}
|
|
2679
|
+
_getFormatLabelText(value, limit) {
|
|
2680
|
+
return value.text;
|
|
2681
|
+
}
|
|
2682
|
+
_adjustY(arcs, maxLabels, attribute, currentMarks) {
|
|
2683
|
+
const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
|
|
2684
|
+
const plotRect = { width: center.x * 2, height: center.y * 2 };
|
|
2685
|
+
const labelLayout = attribute.layout;
|
|
2686
|
+
if (labelLayout.strategy === 'vertical') {
|
|
2687
|
+
let lastY = 0;
|
|
2688
|
+
let delta;
|
|
2689
|
+
const len = arcs.length;
|
|
2690
|
+
if (len <= 0) {
|
|
2691
|
+
return;
|
|
2692
|
+
}
|
|
2693
|
+
for (let i = 0; i < len; i++) {
|
|
2694
|
+
const { y1 } = arcs[i].getLabelBounds();
|
|
2695
|
+
delta = y1 - lastY;
|
|
2696
|
+
if (vutils.isLess(delta, 0)) {
|
|
2697
|
+
const index = this._shiftY(arcs, i, len - 1, -delta);
|
|
2698
|
+
this._shiftY(arcs, index, 0, delta / 2);
|
|
2699
|
+
}
|
|
2700
|
+
const { y2 } = arcs[i].getLabelBounds();
|
|
2701
|
+
lastY = y2;
|
|
2702
|
+
}
|
|
2703
|
+
const { y1: firstY1 } = arcs[0].getLabelBounds();
|
|
2704
|
+
delta = firstY1 - 0;
|
|
2705
|
+
if (vutils.isLess(delta, 0)) {
|
|
2706
|
+
this._shiftY(arcs, 0, len - 1, -delta);
|
|
2707
|
+
}
|
|
2708
|
+
for (let i = arcs.length - 1; i >= 0; i--) {
|
|
2709
|
+
if (arcs[i].getLabelBounds().y2 > plotRect.height) {
|
|
2710
|
+
arcs[i].labelVisible = false;
|
|
2711
|
+
}
|
|
2712
|
+
else {
|
|
2713
|
+
break;
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
else if (labelLayout.strategy !== 'none') {
|
|
2718
|
+
const priorityArcs = arcs.map((arc, i) => {
|
|
2719
|
+
return {
|
|
2720
|
+
arc,
|
|
2721
|
+
originIndex: i,
|
|
2722
|
+
priorityIndex: 0
|
|
2723
|
+
};
|
|
2724
|
+
});
|
|
2725
|
+
priorityArcs.sort((a, b) => {
|
|
2726
|
+
return b.arc.radian - a.arc.radian;
|
|
2727
|
+
});
|
|
2728
|
+
priorityArcs.forEach((priorityArc, i) => {
|
|
2729
|
+
priorityArc.priorityIndex = i;
|
|
2730
|
+
priorityArc.arc.labelVisible = false;
|
|
2731
|
+
});
|
|
2732
|
+
let topLabelIndex = Infinity;
|
|
2733
|
+
let bottomLabelIndex = -Infinity;
|
|
2734
|
+
for (let i = 0; i < maxLabels && i < arcs.length; i++) {
|
|
2735
|
+
this._storeY(arcs);
|
|
2736
|
+
const arc = priorityArcs[i].arc;
|
|
2737
|
+
this._computeYRange(arc, attribute, currentMarks);
|
|
2738
|
+
arc.labelVisible = true;
|
|
2739
|
+
const curY = arc.labelPosition.y;
|
|
2740
|
+
const { lastIndex, nextIndex } = this._findNeighborIndex(arcs, priorityArcs[i]);
|
|
2741
|
+
const lastArc = arcs[lastIndex];
|
|
2742
|
+
const nextArc = arcs[nextIndex];
|
|
2743
|
+
if (lastIndex === -1 && nextIndex !== -1) {
|
|
2744
|
+
const nextY = nextArc.labelPosition.y;
|
|
2745
|
+
if (curY > nextY) {
|
|
2746
|
+
arc.labelPosition.y = nextY - nextArc.labelSize.height / 2 - arc.labelSize.height / 2;
|
|
2747
|
+
}
|
|
2748
|
+
else {
|
|
2749
|
+
this._twoWayShift(arcs, arc, nextArc, nextIndex);
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
else if (lastIndex !== -1 && nextIndex === -1) {
|
|
2753
|
+
const lastY = lastArc.labelPosition.y;
|
|
2754
|
+
if (curY < lastY) {
|
|
2755
|
+
arc.labelPosition.y = lastY + lastArc.labelSize.height / 2 + arc.labelSize.height / 2;
|
|
2756
|
+
}
|
|
2757
|
+
else {
|
|
2758
|
+
this._twoWayShift(arcs, lastArc, arc, priorityArcs[i].originIndex);
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
else if (lastIndex !== -1 && nextIndex !== -1) {
|
|
2762
|
+
const lastY = lastArc.labelPosition.y;
|
|
2763
|
+
const nextY = nextArc.labelPosition.y;
|
|
2764
|
+
if (curY > nextY) {
|
|
2765
|
+
arc.labelPosition.y = nextY - nextArc.labelSize.height / 2 - arc.labelSize.height / 2;
|
|
2766
|
+
this._twoWayShift(arcs, lastArc, arc, priorityArcs[i].originIndex);
|
|
2767
|
+
}
|
|
2768
|
+
else if (curY < lastY) {
|
|
2769
|
+
arc.labelPosition.y = lastY + lastArc.labelSize.height / 2 + arc.labelSize.height / 2;
|
|
2770
|
+
this._twoWayShift(arcs, arc, nextArc, nextIndex);
|
|
2771
|
+
}
|
|
2772
|
+
else {
|
|
2773
|
+
this._twoWayShift(arcs, lastArc, arc, priorityArcs[i].originIndex);
|
|
2774
|
+
this._twoWayShift(arcs, arc, nextArc, nextIndex);
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
const nextTopIndex = Math.min(topLabelIndex, priorityArcs[i].originIndex);
|
|
2778
|
+
const nextBottomIndex = Math.max(bottomLabelIndex, priorityArcs[i].originIndex);
|
|
2779
|
+
let delta;
|
|
2780
|
+
delta = arcs[nextBottomIndex].getLabelBounds().y2 - plotRect.height;
|
|
2781
|
+
if (vutils.isGreater(delta, 0)) {
|
|
2782
|
+
this._shiftY(arcs, nextBottomIndex, 0, -delta);
|
|
2783
|
+
}
|
|
2784
|
+
delta = arcs[nextTopIndex].getLabelBounds().y1 - 0;
|
|
2785
|
+
if (vutils.isLess(delta, 0)) {
|
|
2786
|
+
this._shiftY(arcs, nextTopIndex, arcs.length - 1, -delta);
|
|
2787
|
+
}
|
|
2788
|
+
delta = arcs[nextBottomIndex].getLabelBounds().y2 - plotRect.height;
|
|
2789
|
+
if (vutils.isGreater(delta, 0)) {
|
|
2790
|
+
arc.labelVisible = false;
|
|
2791
|
+
this._restoreY(arcs);
|
|
2792
|
+
break;
|
|
2793
|
+
}
|
|
2794
|
+
else if (labelLayout.tangentConstraint && !this._checkYRange(arcs)) {
|
|
2795
|
+
arc.labelVisible = false;
|
|
2796
|
+
this._restoreY(arcs);
|
|
2797
|
+
}
|
|
2798
|
+
else {
|
|
2799
|
+
topLabelIndex = nextTopIndex;
|
|
2800
|
+
bottomLabelIndex = nextBottomIndex;
|
|
2801
|
+
}
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
_shiftY(arcs, start, end, delta) {
|
|
2806
|
+
const direction = start < end ? 1 : -1;
|
|
2807
|
+
let index = start;
|
|
2808
|
+
while (index !== -1) {
|
|
2809
|
+
arcs[index].labelPosition.y += delta;
|
|
2810
|
+
const nextIndex = this._findNextVisibleIndex(arcs, index, end, direction);
|
|
2811
|
+
if (nextIndex >= 0 && nextIndex < arcs.length) {
|
|
2812
|
+
const { y1: curY1, y2: curY2 } = arcs[index].getLabelBounds();
|
|
2813
|
+
const { y1: nextY1, y2: nextY2 } = arcs[nextIndex].getLabelBounds();
|
|
2814
|
+
if ((direction > 0 && curY2 < nextY1) || (direction < 0 && curY1 > nextY2)) {
|
|
2815
|
+
return index;
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
index = nextIndex;
|
|
2819
|
+
}
|
|
2820
|
+
return end;
|
|
2821
|
+
}
|
|
2822
|
+
_findNextVisibleIndex(arcs, start, end, direction) {
|
|
2823
|
+
const diff = (end - start) * direction;
|
|
2824
|
+
for (let i = 1; i <= diff; i++) {
|
|
2825
|
+
const index = start + i * direction;
|
|
2826
|
+
if (arcs[index].labelVisible) {
|
|
2827
|
+
return index;
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
return -1;
|
|
2831
|
+
}
|
|
2832
|
+
_computePointB(arc, r, attribute, currentMarks) {
|
|
2833
|
+
const labelConfig = attribute;
|
|
2834
|
+
const radiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
|
|
2835
|
+
const line1MinLength = labelConfig.line.line1MinLength;
|
|
2836
|
+
const labelLayout = labelConfig.layout;
|
|
2837
|
+
if (labelLayout.strategy === 'none') {
|
|
2838
|
+
arc.pointB = {
|
|
2839
|
+
x: arc.outerCenter.x,
|
|
2840
|
+
y: arc.outerCenter.y
|
|
2841
|
+
};
|
|
2842
|
+
}
|
|
2843
|
+
else {
|
|
2844
|
+
const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
|
|
2845
|
+
const radius = this.computeRadius(radiusRatio, attribute.width, attribute.height);
|
|
2846
|
+
const { labelPosition, quadrant } = arc;
|
|
2847
|
+
const outerR = Math.max(radius + line1MinLength, currentMarks[0].attribute.outerRadius);
|
|
2848
|
+
const rd = r - outerR;
|
|
2849
|
+
const x = Math.sqrt(r ** 2 - Math.abs(center.y - labelPosition.y) ** 2) - rd;
|
|
2850
|
+
if (vutils.isValidNumber(x)) {
|
|
2851
|
+
arc.pointB = {
|
|
2852
|
+
x: center.x + x * (isQuadrantLeft(quadrant) ? -1 : 1),
|
|
2853
|
+
y: labelPosition.y
|
|
2854
|
+
};
|
|
2855
|
+
}
|
|
2856
|
+
else {
|
|
2857
|
+
arc.pointB = { x: NaN, y: NaN };
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
_storeY(arcs) {
|
|
2862
|
+
for (const arc of arcs) {
|
|
2863
|
+
if (arc.labelVisible) {
|
|
2864
|
+
arc.lastLabelY = arc.labelPosition.y;
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
_computeYRange(arc, attribute, currentMarks) {
|
|
2869
|
+
const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
|
|
2870
|
+
const plotRect = { width: center.x * 2, height: center.y * 2 };
|
|
2871
|
+
const radiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
|
|
2872
|
+
const line1MinLength = attribute.line.line1MinLength;
|
|
2873
|
+
const { width, height } = plotRect;
|
|
2874
|
+
const radius = this.computeRadius(radiusRatio, attribute.width, attribute.height);
|
|
2875
|
+
const r = this._computeLayoutRadius(height / 2, attribute, currentMarks);
|
|
2876
|
+
const cx = Math.abs(arc.center.x - width / 2);
|
|
2877
|
+
const cy = arc.center.y - height / 2;
|
|
2878
|
+
let a;
|
|
2879
|
+
let b;
|
|
2880
|
+
let c;
|
|
2881
|
+
if (vutils.isNumberClose(width / 2, cx)) {
|
|
2882
|
+
a = 0;
|
|
2883
|
+
b = 1;
|
|
2884
|
+
c = -cy;
|
|
2885
|
+
}
|
|
2886
|
+
else if (vutils.isNumberClose(height / 2, cy)) {
|
|
2887
|
+
a = 1;
|
|
2888
|
+
b = 0;
|
|
2889
|
+
c = -cx;
|
|
2890
|
+
}
|
|
2891
|
+
else {
|
|
2892
|
+
const k = -1 / (cy / cx);
|
|
2893
|
+
a = k;
|
|
2894
|
+
b = -1;
|
|
2895
|
+
c = cy - k * cx;
|
|
2896
|
+
}
|
|
2897
|
+
const points = lineCirclePoints(a, b, c, line1MinLength + radius - r, 0, r);
|
|
2898
|
+
if (points.length < 2) {
|
|
2899
|
+
return;
|
|
2900
|
+
}
|
|
2901
|
+
let min;
|
|
2902
|
+
let max;
|
|
2903
|
+
if (points[0].x > points[1].x) {
|
|
2904
|
+
points.reverse();
|
|
2905
|
+
}
|
|
2906
|
+
if (points[0].x < 0) {
|
|
2907
|
+
if (vutils.isNumberClose(points[0].y, points[1].y)) {
|
|
2908
|
+
if (Math.abs(arc.middleAngle) < Math.PI / 2) {
|
|
2909
|
+
min = 0;
|
|
2910
|
+
max = points[1].y + height / 2;
|
|
2911
|
+
}
|
|
2912
|
+
else {
|
|
2913
|
+
min = points[1].y + height / 2;
|
|
2914
|
+
max = height;
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
else if (points[0].y < points[1].y) {
|
|
2918
|
+
min = 0;
|
|
2919
|
+
max = points[1].y + height / 2;
|
|
2920
|
+
}
|
|
2921
|
+
else {
|
|
2922
|
+
min = points[1].y + height / 2;
|
|
2923
|
+
max = plotRect.height;
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
else {
|
|
2927
|
+
min = Math.min(points[0].y, points[1].y) + height / 2;
|
|
2928
|
+
max = Math.max(points[0].y, points[1].y) + height / 2;
|
|
2929
|
+
}
|
|
2930
|
+
arc.labelYRange = [min, max];
|
|
2931
|
+
}
|
|
2932
|
+
_computeLayoutRadius(halfYLength, attribute, currentMarks) {
|
|
2933
|
+
const labelConfig = attribute;
|
|
2934
|
+
const layoutArcGap = labelConfig.layoutArcGap;
|
|
2935
|
+
const line1MinLength = labelConfig.line.line1MinLength;
|
|
2936
|
+
const radiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
|
|
2937
|
+
const radius = this.computeRadius(radiusRatio, attribute.width, attribute.height);
|
|
2938
|
+
const outerR = radius + line1MinLength;
|
|
2939
|
+
const a = outerR - layoutArcGap;
|
|
2940
|
+
return Math.max((a ** 2 + halfYLength ** 2) / (2 * a), outerR);
|
|
2941
|
+
}
|
|
2942
|
+
_findNeighborIndex(arcs, priorityArc) {
|
|
2943
|
+
const index = priorityArc.originIndex;
|
|
2944
|
+
let lastIndex = -1;
|
|
2945
|
+
let nextIndex = -1;
|
|
2946
|
+
for (let i = index - 1; i >= 0; i--) {
|
|
2947
|
+
if (arcs[i].labelVisible) {
|
|
2948
|
+
lastIndex = i;
|
|
2949
|
+
break;
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2952
|
+
for (let i = index + 1; i < arcs.length; i++) {
|
|
2953
|
+
if (arcs[i].labelVisible) {
|
|
2954
|
+
nextIndex = i;
|
|
2955
|
+
break;
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
return {
|
|
2959
|
+
lastIndex,
|
|
2960
|
+
nextIndex
|
|
2961
|
+
};
|
|
2962
|
+
}
|
|
2963
|
+
_twoWayShift(arcs, lastArc, nextArc, nextIndex) {
|
|
2964
|
+
const delta = nextArc.getLabelBounds().y1 - lastArc.getLabelBounds().y2;
|
|
2965
|
+
if (vutils.isLess(delta, 0)) {
|
|
2966
|
+
const i = this._shiftY(arcs, nextIndex, arcs.length - 1, -delta);
|
|
2967
|
+
this._shiftY(arcs, i, 0, delta / 2);
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
_restoreY(arcs) {
|
|
2971
|
+
for (const arc of arcs) {
|
|
2972
|
+
if (arc.labelVisible) {
|
|
2973
|
+
arc.labelPosition.y = arc.lastLabelY;
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2976
|
+
}
|
|
2977
|
+
_checkYRange(arcs) {
|
|
2978
|
+
for (const arc of arcs) {
|
|
2979
|
+
const { labelYRange, labelPosition } = arc;
|
|
2980
|
+
if (arc.labelVisible &&
|
|
2981
|
+
labelYRange &&
|
|
2982
|
+
(vutils.isLess(labelPosition.y, labelYRange[0]) || vutils.isGreater(labelPosition.y, labelYRange[1]))) {
|
|
2983
|
+
return false;
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
return true;
|
|
2987
|
+
}
|
|
2988
|
+
_coverLabels(arcs) {
|
|
2989
|
+
if (arcs.length <= 1) {
|
|
2990
|
+
return;
|
|
2991
|
+
}
|
|
2992
|
+
let lastBounds = arcs[0].getLabelBounds();
|
|
2993
|
+
for (let i = 1; i < arcs.length; i++) {
|
|
2994
|
+
const bounds = arcs[i].getLabelBounds();
|
|
2995
|
+
if (!checkBoundsOverlap(lastBounds, bounds)) {
|
|
2996
|
+
lastBounds = bounds;
|
|
2997
|
+
}
|
|
2998
|
+
else {
|
|
2999
|
+
arcs[i].labelVisible = false;
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
computeRadius(r, width, height, k) {
|
|
3004
|
+
return this.computeLayoutRadius(width ? width : 0, height ? height : 0) * r * (vutils.isNil(k) ? 1 : k);
|
|
3005
|
+
}
|
|
3006
|
+
computeLayoutRadius(width, height) {
|
|
3007
|
+
return Math.min(width / 2, height / 2);
|
|
3008
|
+
}
|
|
3009
|
+
computeLayoutOuterRadius(r, width, height) {
|
|
3010
|
+
return r / (Math.min(width, height) / 2);
|
|
3011
|
+
}
|
|
3012
|
+
computeDatumRadius(width, height, outerRadius) {
|
|
3013
|
+
const outerRadiusRatio = this.computeLayoutOuterRadius(outerRadius, width, height);
|
|
3014
|
+
return this.computeLayoutRadius(width ? width : 0, height ? height : 0) * outerRadiusRatio;
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
|
|
2206
3018
|
const labelComponentMap = {
|
|
2207
3019
|
rect: RectLabel,
|
|
2208
|
-
symbol: SymbolLabel
|
|
3020
|
+
symbol: SymbolLabel,
|
|
3021
|
+
arc: ArcLabel
|
|
2209
3022
|
};
|
|
2210
3023
|
class DataLabel extends AbstractComponent {
|
|
2211
3024
|
name = 'data-label';
|
|
@@ -8896,17 +9709,6 @@
|
|
|
8896
9709
|
}
|
|
8897
9710
|
}
|
|
8898
9711
|
|
|
8899
|
-
exports.IOperateType = void 0;
|
|
8900
|
-
(function (IOperateType) {
|
|
8901
|
-
IOperateType["drawStart"] = "drawStart";
|
|
8902
|
-
IOperateType["drawEnd"] = "drawEnd";
|
|
8903
|
-
IOperateType["drawing"] = "drawing";
|
|
8904
|
-
IOperateType["moving"] = "moving";
|
|
8905
|
-
IOperateType["moveStart"] = "moveStart";
|
|
8906
|
-
IOperateType["moveEnd"] = "moveEnd";
|
|
8907
|
-
IOperateType["brushClear"] = "brushClear";
|
|
8908
|
-
})(exports.IOperateType || (exports.IOperateType = {}));
|
|
8909
|
-
|
|
8910
9712
|
const DEFAULT_BRUSH_ATTRIBUTES = {
|
|
8911
9713
|
brushMode: 'single',
|
|
8912
9714
|
brushType: 'rect',
|
|
@@ -8938,8 +9740,6 @@
|
|
|
8938
9740
|
_container;
|
|
8939
9741
|
_activeDrawState = false;
|
|
8940
9742
|
_cacheDrawPoints = [];
|
|
8941
|
-
_cacheStartTime;
|
|
8942
|
-
_isDrawedBeforeEnd = false;
|
|
8943
9743
|
_activeMoveState = false;
|
|
8944
9744
|
_operatingMaskMoveDx = 0;
|
|
8945
9745
|
_operatingMaskMoveDy = 0;
|
|
@@ -8995,41 +9795,36 @@
|
|
|
8995
9795
|
this._activeMoveState && this._moving(e);
|
|
8996
9796
|
};
|
|
8997
9797
|
_onBrushEnd = (e) => {
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
this._container.incrementalClearChild();
|
|
9001
|
-
this._updateDragMaskCallback &&
|
|
9002
|
-
this._updateDragMaskCallback({
|
|
9003
|
-
operateType: exports.IOperateType.brushClear,
|
|
9004
|
-
operateMask: this._operatingMask,
|
|
9005
|
-
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
9006
|
-
});
|
|
9007
|
-
}
|
|
9008
|
-
else {
|
|
9009
|
-
this._updateDragMaskCallback &&
|
|
9010
|
-
this._updateDragMaskCallback({
|
|
9011
|
-
operateType: this._activeDrawState ? exports.IOperateType.drawEnd : exports.IOperateType.moveEnd,
|
|
9012
|
-
operateMask: this._operatingMask,
|
|
9013
|
-
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
9014
|
-
});
|
|
9798
|
+
if (this._outOfInteractiveRange(e)) {
|
|
9799
|
+
return;
|
|
9015
9800
|
}
|
|
9801
|
+
this._updateDragMaskCallback &&
|
|
9802
|
+
this._updateDragMaskCallback({
|
|
9803
|
+
operateType: this._activeDrawState ? 'brushEnd' : 'brushMaskUp',
|
|
9804
|
+
operateMask: this._operatingMask,
|
|
9805
|
+
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
9806
|
+
});
|
|
9016
9807
|
this._activeDrawState = false;
|
|
9017
9808
|
this._activeMoveState = false;
|
|
9018
|
-
this._isDrawedBeforeEnd = false;
|
|
9019
9809
|
this._operatingMask.setAttribute('pickable', false);
|
|
9020
9810
|
};
|
|
9021
9811
|
_initDraw(e) {
|
|
9022
|
-
const { brushMode } = this.attribute;
|
|
9812
|
+
const { brushMode, removeOnClick } = this.attribute;
|
|
9023
9813
|
const pos = this.eventPosToStagePos(e);
|
|
9024
9814
|
this._cacheDrawPoints = [pos];
|
|
9025
|
-
this.
|
|
9026
|
-
|
|
9815
|
+
if (!this._operatingMask) {
|
|
9816
|
+
this._addBrushMask();
|
|
9817
|
+
}
|
|
9818
|
+
if (brushMode === 'single' && removeOnClick) {
|
|
9027
9819
|
this._container.incrementalClearChild();
|
|
9820
|
+
this._addBrushMask();
|
|
9821
|
+
}
|
|
9822
|
+
else if (brushMode === 'multiple') {
|
|
9823
|
+
this._addBrushMask();
|
|
9028
9824
|
}
|
|
9029
|
-
this._addBrushMask();
|
|
9030
9825
|
this._updateDragMaskCallback &&
|
|
9031
9826
|
this._updateDragMaskCallback({
|
|
9032
|
-
operateType:
|
|
9827
|
+
operateType: 'brushStart',
|
|
9033
9828
|
operateMask: this._operatingMask,
|
|
9034
9829
|
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
9035
9830
|
});
|
|
@@ -9050,14 +9845,13 @@
|
|
|
9050
9845
|
this._operatingMask.setAttribute('pickable', true);
|
|
9051
9846
|
this._updateDragMaskCallback &&
|
|
9052
9847
|
this._updateDragMaskCallback({
|
|
9053
|
-
operateType:
|
|
9848
|
+
operateType: 'brushMaskDown',
|
|
9054
9849
|
operateMask: this._operatingMask,
|
|
9055
9850
|
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
9056
9851
|
});
|
|
9057
9852
|
}
|
|
9058
9853
|
_drawing(e) {
|
|
9059
9854
|
const pos = this.eventPosToStagePos(e);
|
|
9060
|
-
this._isDrawedBeforeEnd = true;
|
|
9061
9855
|
if (this._cacheDrawPoints.length > 0) {
|
|
9062
9856
|
const lastPos = this._cacheDrawPoints[this._cacheDrawPoints.length - 1];
|
|
9063
9857
|
if (pos.x === lastPos?.x && pos.y === lastPos?.y) {
|
|
@@ -9070,7 +9864,7 @@
|
|
|
9070
9864
|
this._brushMaskAABBBoundsDict[this._operatingMask.name] = this._operatingMask.AABBBounds;
|
|
9071
9865
|
this._updateDragMaskCallback &&
|
|
9072
9866
|
this._updateDragMaskCallback({
|
|
9073
|
-
operateType:
|
|
9867
|
+
operateType: 'brushing',
|
|
9074
9868
|
operateMask: this._operatingMask,
|
|
9075
9869
|
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
9076
9870
|
});
|
|
@@ -9094,7 +9888,7 @@
|
|
|
9094
9888
|
this._brushMaskAABBBoundsDict[this._operatingMask.name] = this._operatingMask.AABBBounds;
|
|
9095
9889
|
this._updateDragMaskCallback &&
|
|
9096
9890
|
this._updateDragMaskCallback({
|
|
9097
|
-
operateType:
|
|
9891
|
+
operateType: 'brushMaskMove',
|
|
9098
9892
|
operateMask: this._operatingMask,
|
|
9099
9893
|
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict
|
|
9100
9894
|
});
|
|
@@ -9621,9 +10415,11 @@
|
|
|
9621
10415
|
}
|
|
9622
10416
|
}
|
|
9623
10417
|
|
|
9624
|
-
const version = "0.13.9-alpha.
|
|
10418
|
+
const version = "0.13.9-alpha.8";
|
|
9625
10419
|
|
|
9626
10420
|
exports.AbstractComponent = AbstractComponent;
|
|
10421
|
+
exports.ArcInfo = ArcInfo;
|
|
10422
|
+
exports.ArcLabel = ArcLabel;
|
|
9627
10423
|
exports.BasePlayer = BasePlayer;
|
|
9628
10424
|
exports.Brush = Brush;
|
|
9629
10425
|
exports.CircleAxis = CircleAxis;
|