@visactor/vrender-components 0.13.9-alpha.1 → 0.13.9-alpha.5

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.
Files changed (55) hide show
  1. package/cjs/index.d.ts +1 -1
  2. package/cjs/index.js +1 -1
  3. package/cjs/index.js.map +1 -1
  4. package/cjs/label/arc.d.ts +69 -0
  5. package/cjs/label/arc.js +397 -0
  6. package/cjs/label/arc.js.map +1 -0
  7. package/cjs/label/base.d.ts +3 -1
  8. package/cjs/label/base.js +69 -30
  9. package/cjs/label/base.js.map +1 -1
  10. package/cjs/label/dataLabel.js +3 -2
  11. package/cjs/label/dataLabel.js.map +1 -1
  12. package/cjs/label/index.d.ts +1 -0
  13. package/cjs/label/index.js +2 -1
  14. package/cjs/label/index.js.map +1 -1
  15. package/cjs/label/type.d.ts +41 -2
  16. package/cjs/label/type.js.map +1 -1
  17. package/cjs/label/util.d.ts +12 -0
  18. package/cjs/label/util.js +113 -0
  19. package/cjs/label/util.js.map +1 -0
  20. package/cjs/link-path/type.js +1 -2
  21. package/cjs/marker/base.js +2 -1
  22. package/cjs/pager/index.js +1 -1
  23. package/cjs/pager/pager.js +1 -1
  24. package/cjs/util/common.d.ts +1 -3
  25. package/cjs/util/common.js +2 -14
  26. package/cjs/util/common.js.map +1 -1
  27. package/dist/index.js +853 -61
  28. package/dist/index.min.js +1 -1
  29. package/es/index.d.ts +1 -1
  30. package/es/index.js +1 -1
  31. package/es/index.js.map +1 -1
  32. package/es/label/arc.d.ts +69 -0
  33. package/es/label/arc.js +387 -0
  34. package/es/label/arc.js.map +1 -0
  35. package/es/label/base.d.ts +3 -1
  36. package/es/label/base.js +71 -32
  37. package/es/label/base.js.map +1 -1
  38. package/es/label/dataLabel.js +4 -1
  39. package/es/label/dataLabel.js.map +1 -1
  40. package/es/label/index.d.ts +1 -0
  41. package/es/label/index.js +2 -0
  42. package/es/label/index.js.map +1 -1
  43. package/es/label/type.d.ts +41 -2
  44. package/es/label/type.js.map +1 -1
  45. package/es/label/util.d.ts +12 -0
  46. package/es/label/util.js +99 -0
  47. package/es/label/util.js.map +1 -0
  48. package/es/link-path/type.js +1 -2
  49. package/es/marker/base.js +2 -1
  50. package/es/pager/index.js +1 -1
  51. package/es/pager/pager.js +1 -1
  52. package/es/util/common.d.ts +1 -3
  53. package/es/util/common.js +0 -12
  54. package/es/util/common.js.map +1 -1
  55. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -341,26 +341,6 @@
341
341
  }
342
342
  return obj.visible !== false;
343
343
  };
344
- function getMarksByName(root, name) {
345
- if (!name) {
346
- return [];
347
- }
348
- const group = root.find(node => node.name === name, true);
349
- if (!group) {
350
- return [];
351
- }
352
- return group.getChildren();
353
- }
354
- function getNoneGroupMarksByName(root, name) {
355
- if (!name) {
356
- return [];
357
- }
358
- const group = root.find(node => node.name === name, true);
359
- if (!group) {
360
- return [];
361
- }
362
- return group.findAll(node => node.type !== 'group', true);
363
- }
364
344
 
365
345
  const defaultAlternativeColors = ['#ffffff', '#000000'];
366
346
  function labelSmartInvert(foregroundColorOrigin, backgroundColorOrogin, textType, contrastRatiosThreshold, alternativeColors) {
@@ -1612,6 +1592,10 @@
1612
1592
  _lastHover;
1613
1593
  _lastSelect;
1614
1594
  _enableAnimation;
1595
+ layoutArcLabels(position, attribute, currentMarks) {
1596
+ const arcs = [];
1597
+ return arcs;
1598
+ }
1615
1599
  render() {
1616
1600
  this._prepare();
1617
1601
  const { overlap, smartInvert, dataFilter, customLayoutFunc, customOverlapFunc } = this.attribute;
@@ -1625,12 +1609,14 @@
1625
1609
  }
1626
1610
  else {
1627
1611
  labels = this.layout(data);
1628
- if (vutils.isFunction(customOverlapFunc)) {
1629
- labels = customOverlapFunc(labels, (d) => this._idToGraphic.get(d.id));
1630
- }
1631
- else {
1632
- if (overlap !== false) {
1633
- labels = this._overlapping(labels);
1612
+ if (this.attribute.type !== 'arc') {
1613
+ if (vutils.isFunction(customOverlapFunc)) {
1614
+ labels = customOverlapFunc(labels, (d) => this._idToGraphic.get(d.id));
1615
+ }
1616
+ else {
1617
+ if (overlap !== false) {
1618
+ labels = this._overlapping(labels);
1619
+ }
1634
1620
  }
1635
1621
  }
1636
1622
  }
@@ -1714,7 +1700,7 @@
1714
1700
  return text;
1715
1701
  }
1716
1702
  _prepare() {
1717
- const baseMarks = getMarksByName(this.getRootNode(), this.attribute.baseMarkGroupName);
1703
+ const baseMarks = this.getBaseMarks();
1718
1704
  const currentBaseMarks = [];
1719
1705
  baseMarks.forEach(mark => {
1720
1706
  if (mark.releaseStatus !== 'willRelease') {
@@ -1751,20 +1737,47 @@
1751
1737
  const textData = data[i];
1752
1738
  const baseMark = this._idToGraphic.get(textData.id);
1753
1739
  const labelAttribute = {
1740
+ fill: baseMark.attribute.fill,
1754
1741
  ...textStyle,
1755
1742
  ...textData
1756
1743
  };
1757
1744
  const text = this._createLabelText(labelAttribute);
1758
1745
  const textBounds = this.getGraphicBounds(text);
1759
1746
  const graphicBounds = this.getGraphicBounds(baseMark, { x: textData.x, y: textData.y });
1760
- const textLocation = this.labeling(textBounds, graphicBounds, vutils.isFunction(position) ? position(textData) : position, offset);
1761
- if (!textLocation) {
1762
- continue;
1747
+ if (this.attribute.type === 'arc') {
1748
+ const graphicAttributes = baseMark.attribute;
1749
+ const { width, height } = this.attribute;
1750
+ this.labeling(textBounds, graphicBounds, vutils.isFunction(position) ? position(textData) : position, offset, graphicAttributes, textData, width, height, this.attribute);
1751
+ labels.push(text);
1752
+ }
1753
+ else {
1754
+ const textLocation = this.labeling(textBounds, graphicBounds, vutils.isFunction(position) ? position(textData) : position, offset);
1755
+ if (!textLocation) {
1756
+ continue;
1757
+ }
1758
+ labelAttribute.x = textLocation.x;
1759
+ labelAttribute.y = textLocation.y;
1760
+ text.setAttributes(textLocation);
1761
+ labels.push(text);
1762
+ }
1763
+ }
1764
+ if (this.attribute.type === 'arc') {
1765
+ const arcs = this.layoutArcLabels(position, this.attribute, Array.from(this._idToGraphic.values()));
1766
+ for (let i = 0; i < data.length; i++) {
1767
+ const textData = data[i];
1768
+ const basedArc = arcs.find(arc => arc.labelText === textData.text);
1769
+ const labelAttribute = {
1770
+ x: basedArc.labelPosition.x,
1771
+ y: basedArc.labelPosition.y,
1772
+ textAlign: this.attribute.textAlign ?? basedArc.textAlign,
1773
+ textBaseline: this.attribute.textBaseline ?? basedArc.textBaseline,
1774
+ angle: this.attribute.angle ?? basedArc.angle
1775
+ };
1776
+ labels[i].setAttributes(labelAttribute);
1777
+ labels[i].pointA = basedArc.pointA;
1778
+ labels[i].pointB = basedArc.pointB;
1779
+ labels[i].pointC = basedArc.pointC;
1763
1780
  }
1764
- labelAttribute.x = textLocation.x;
1765
- labelAttribute.y = textLocation.y;
1766
- text.setAttributes(textLocation);
1767
- labels.push(text);
1768
1781
  }
1769
1782
  return labels;
1770
1783
  }
@@ -1782,7 +1795,7 @@
1782
1795
  if (size.width === 0 || size.height === 0) {
1783
1796
  return labels;
1784
1797
  }
1785
- const { avoidBaseMark, strategy = [], hideOnHit = true, clampForce = true, avoidMarks = [] } = option;
1798
+ const { avoidBaseMark, strategy = [], hideOnHit = true, clampForce = true } = option;
1786
1799
  const bmpTool = this._bmpTool || bitmapTool(size.width, size.height);
1787
1800
  const bitmap = this._bitmap || bmpTool.bitmap();
1788
1801
  const checkBounds = strategy.some(s => s.type === 'bound');
@@ -1791,18 +1804,6 @@
1791
1804
  mark.AABBBounds && bitmap.setRange(boundToRange(bmpTool, mark.AABBBounds, true));
1792
1805
  });
1793
1806
  }
1794
- if (avoidMarks.length > 0) {
1795
- avoidMarks.forEach(avoid => {
1796
- if (vutils.isString(avoid)) {
1797
- getNoneGroupMarksByName(this.getRootNode(), avoid).forEach(avoidMark => {
1798
- avoidMark.AABBBounds && bitmap.setRange(boundToRange(bmpTool, avoidMark.AABBBounds, true));
1799
- });
1800
- }
1801
- else if (avoid.AABBBounds) {
1802
- bitmap.setRange(boundToRange(bmpTool, avoid.AABBBounds, true));
1803
- }
1804
- });
1805
- }
1806
1807
  for (let i = 0; i < labels.length; i++) {
1807
1808
  if (labels[i].visible === false) {
1808
1809
  continue;
@@ -1822,16 +1823,7 @@
1822
1823
  continue;
1823
1824
  }
1824
1825
  }
1825
- let hasPlace = false;
1826
- for (let j = 0; j < strategy.length; j++) {
1827
- hasPlace = place(bmpTool, bitmap, strategy[j], this.attribute, text, this.getGraphicBounds(baseMark, labels[i]), this.labeling);
1828
- if (hasPlace !== false) {
1829
- text.setAttributes({ x: hasPlace.x, y: hasPlace.y });
1830
- result.push(text);
1831
- break;
1832
- }
1833
- }
1834
- if (!hasPlace && clampForce) {
1826
+ if (clampForce) {
1835
1827
  const { dx = 0, dy = 0 } = clampText(text, bmpTool.width, bmpTool.height);
1836
1828
  if (!(dx === 0 && dy === 0) &&
1837
1829
  canPlace(bmpTool, bitmap, {
@@ -1841,11 +1833,19 @@
1841
1833
  y2: text.AABBBounds.y2 + dy
1842
1834
  })) {
1843
1835
  text.setAttributes({ x: text.attribute.x + dx, y: text.attribute.y + dy });
1844
- bitmap.setRange(boundToRange(bmpTool, text.AABBBounds, true));
1845
1836
  result.push(text);
1846
1837
  continue;
1847
1838
  }
1848
1839
  }
1840
+ let hasPlace = false;
1841
+ for (let j = 0; j < strategy.length; j++) {
1842
+ hasPlace = place(bmpTool, bitmap, strategy[j], this.attribute, text, this.getGraphicBounds(baseMark, labels[i]), this.labeling);
1843
+ if (hasPlace !== false) {
1844
+ text.setAttributes({ x: hasPlace.x, y: hasPlace.y });
1845
+ result.push(text);
1846
+ break;
1847
+ }
1848
+ }
1849
1849
  !hasPlace && !hideOnHit && result.push(text);
1850
1850
  }
1851
1851
  if (vutils.isFunction(this.onAfterLabelOverlap)) {
@@ -1853,6 +1853,13 @@
1853
1853
  }
1854
1854
  return result;
1855
1855
  }
1856
+ getBaseMarks() {
1857
+ const baseMarkGroup = this.getBaseMarkGroup();
1858
+ if (!baseMarkGroup) {
1859
+ return;
1860
+ }
1861
+ return baseMarkGroup.getChildren();
1862
+ }
1856
1863
  getBaseMarkGroup() {
1857
1864
  const { baseMarkGroupName } = this.attribute;
1858
1865
  if (!baseMarkGroupName) {
@@ -1880,14 +1887,29 @@
1880
1887
  const prevTextMap = this._graphicToText || new Map();
1881
1888
  const texts = [];
1882
1889
  labels.forEach((text, index) => {
1890
+ let labelLine;
1891
+ if (this.attribute.type === 'arc' && this.attribute.position === 'outside') {
1892
+ labelLine = vrender.createPath({
1893
+ visible: text.attribute?.visible ?? true,
1894
+ stroke: text.attribute?.line?.stroke ?? text.attribute?.fill,
1895
+ lineWidth: 1,
1896
+ path: `M${Math.round(text.pointA.x)},${Math.round(text.pointA.y)}` +
1897
+ ` L${Math.round(text.pointB.x)},${Math.round(text.pointB.y)}` +
1898
+ ` L${Math.round(text.pointC.x)},${Math.round(text.pointC.y)}`
1899
+ });
1900
+ }
1883
1901
  const relatedGraphic = this._idToGraphic.get(text.attribute.id);
1884
1902
  const state = prevTextMap?.get(relatedGraphic) ? 'update' : 'enter';
1885
1903
  if (state === 'enter') {
1886
1904
  texts.push(text);
1905
+ if (this.attribute.type === 'arc' && this.attribute.position === 'outside') ;
1887
1906
  currentTextMap.set(relatedGraphic, text);
1888
1907
  if (!disableAnimation && relatedGraphic) {
1889
1908
  const { from, to } = getAnimationAttributes(text.attribute, 'fadeIn');
1890
1909
  this.add(text);
1910
+ if (this.attribute.type === 'arc' && this.attribute.position === 'outside') {
1911
+ this.add(labelLine);
1912
+ }
1891
1913
  relatedGraphic.onAnimateBind = () => {
1892
1914
  text.setAttributes(from);
1893
1915
  const listener = this._afterRelatedGraphicAttributeUpdate(text, texts, index, relatedGraphic, {
@@ -1995,7 +2017,15 @@
1995
2017
  continue;
1996
2018
  }
1997
2019
  const baseMark = this._idToGraphic.get(label.attribute.id);
1998
- const isInside = canPlaceInside(label.AABBBounds, baseMark?.AABBBounds);
2020
+ let isInside = canPlaceInside(label.AABBBounds, baseMark?.AABBBounds);
2021
+ if (this.attribute.type === 'arc') {
2022
+ if (this.attribute.position === 'inside') {
2023
+ isInside = true;
2024
+ }
2025
+ else {
2026
+ isInside = false;
2027
+ }
2028
+ }
1999
2029
  if (label.attribute.stroke && label.attribute.lineWidth > 0) {
2000
2030
  label.setAttributes({
2001
2031
  fill: labelSmartInvert(label.attribute.fill, label.attribute.stroke, textType, contrastRatiosThreshold, alternativeColors)
@@ -2222,9 +2252,769 @@
2222
2252
  }
2223
2253
  }
2224
2254
 
2255
+ function polarToCartesian(point) {
2256
+ if (!point.radius) {
2257
+ return { x: 0, y: 0 };
2258
+ }
2259
+ return {
2260
+ x: Math.cos(point.angle) * point.radius,
2261
+ y: Math.sin(point.angle) * point.radius
2262
+ };
2263
+ }
2264
+ function circlePoint(x0, y0, radius, radian) {
2265
+ const offset = polarToCartesian({
2266
+ radius,
2267
+ angle: radian
2268
+ });
2269
+ return {
2270
+ x: x0 + offset.x,
2271
+ y: y0 + offset.y
2272
+ };
2273
+ }
2274
+ function computeQuadrant(angle) {
2275
+ angle = normalizeAngle(angle);
2276
+ if (angle > 0 && angle <= Math.PI / 2) {
2277
+ return 2;
2278
+ }
2279
+ else if (angle > Math.PI / 2 && angle <= Math.PI) {
2280
+ return 3;
2281
+ }
2282
+ else if (angle > Math.PI && angle <= (3 * Math.PI) / 2) {
2283
+ return 4;
2284
+ }
2285
+ return 1;
2286
+ }
2287
+ function normalizeAngle(angle) {
2288
+ while (angle < 0) {
2289
+ angle += Math.PI * 2;
2290
+ }
2291
+ while (angle >= Math.PI * 2) {
2292
+ angle -= Math.PI * 2;
2293
+ }
2294
+ return angle;
2295
+ }
2296
+ function isQuadrantLeft(quadrant) {
2297
+ return quadrant === 3 || quadrant === 4;
2298
+ }
2299
+ function isQuadrantRight(quadrant) {
2300
+ return quadrant === 1 || quadrant === 2;
2301
+ }
2302
+ function lineCirclePoints(a, b, c, x0, y0, r) {
2303
+ if ((a === 0 && b === 0) || r <= 0) {
2304
+ return [];
2305
+ }
2306
+ if (a === 0) {
2307
+ const y1 = -c / b;
2308
+ const fy = (y1 - y0) ** 2;
2309
+ const fd = r ** 2 - fy;
2310
+ if (fd < 0) {
2311
+ return [];
2312
+ }
2313
+ else if (fd === 0) {
2314
+ return [{ x: x0, y: y1 }];
2315
+ }
2316
+ const x1 = Math.sqrt(fd) + x0;
2317
+ const x2 = -Math.sqrt(fd) + x0;
2318
+ return [
2319
+ { x: x1, y: y1 },
2320
+ { x: x2, y: y1 }
2321
+ ];
2322
+ }
2323
+ else if (b === 0) {
2324
+ const x1 = -c / a;
2325
+ const fx = (x1 - x0) ** 2;
2326
+ const fd = r ** 2 - fx;
2327
+ if (fd < 0) {
2328
+ return [];
2329
+ }
2330
+ else if (fd === 0) {
2331
+ return [{ x: x1, y: y0 }];
2332
+ }
2333
+ const y1 = Math.sqrt(fd) + y0;
2334
+ const y2 = -Math.sqrt(fd) + y0;
2335
+ return [
2336
+ { x: x1, y: y1 },
2337
+ { x: x1, y: y2 }
2338
+ ];
2339
+ }
2340
+ const fa = (b / a) ** 2 + 1;
2341
+ const fb = 2 * ((c / a + x0) * (b / a) - y0);
2342
+ const fc = (c / a + x0) ** 2 + y0 ** 2 - r ** 2;
2343
+ const fd = fb ** 2 - 4 * fa * fc;
2344
+ if (fd < 0) {
2345
+ return [];
2346
+ }
2347
+ const y1 = (-fb + Math.sqrt(fd)) / (2 * fa);
2348
+ const y2 = (-fb - Math.sqrt(fd)) / (2 * fa);
2349
+ const x1 = -(b * y1 + c) / a;
2350
+ const x2 = -(b * y2 + c) / a;
2351
+ if (fd === 0) {
2352
+ return [{ x: x1, y: y1 }];
2353
+ }
2354
+ return [
2355
+ { x: x1, y: y1 },
2356
+ { x: x2, y: y2 }
2357
+ ];
2358
+ }
2359
+ function connectLineRadian(radius, length) {
2360
+ if (length > radius * 2) {
2361
+ return NaN;
2362
+ }
2363
+ return Math.asin(length / 2 / radius) * 2;
2364
+ }
2365
+ function checkBoundsOverlap(boundsA, boundsB) {
2366
+ const { x1: ax1, y1: ay1, x2: ax2, y2: ay2 } = boundsA;
2367
+ const { x1: bx1, y1: by1, x2: bx2, y2: by2 } = boundsB;
2368
+ return !((ax1 <= bx1 && ax2 <= bx1) ||
2369
+ (ax1 >= bx2 && ax2 >= bx2) ||
2370
+ (ay1 <= by1 && ay2 <= by1) ||
2371
+ (ay1 >= by2 && ay2 >= by2));
2372
+ }
2373
+
2374
+ class ArcInfo {
2375
+ key;
2376
+ refDatum;
2377
+ center;
2378
+ outerCenter;
2379
+ labelSize;
2380
+ labelPosition;
2381
+ labelLimit;
2382
+ labelVisible;
2383
+ lastLabelY;
2384
+ labelYRange;
2385
+ labelText;
2386
+ pointA;
2387
+ pointB;
2388
+ pointC;
2389
+ quadrant;
2390
+ radian;
2391
+ middleAngle;
2392
+ k;
2393
+ textAlign;
2394
+ textBaseline;
2395
+ angle;
2396
+ constructor(refDatum, center, outerCenter, quadrant, radian, middleAngle) {
2397
+ this.refDatum = refDatum;
2398
+ this.center = center;
2399
+ this.outerCenter = outerCenter;
2400
+ this.quadrant = quadrant;
2401
+ this.radian = radian;
2402
+ this.middleAngle = middleAngle;
2403
+ this.labelVisible = true;
2404
+ this.labelLimit = 0;
2405
+ }
2406
+ getLabelBounds() {
2407
+ if (!this.labelPosition || !this.labelSize) {
2408
+ return { x1: 0, x2: 0, y1: 0, y2: 0 };
2409
+ }
2410
+ return {
2411
+ x1: this.labelPosition.x - this.labelSize.width / 2,
2412
+ y1: this.labelPosition.y - this.labelSize.height / 2,
2413
+ x2: this.labelPosition.x + this.labelSize.width / 2,
2414
+ y2: this.labelPosition.y + this.labelSize.height / 2
2415
+ };
2416
+ }
2417
+ }
2418
+ class ArcLabel extends LabelBase {
2419
+ name = 'arc-label';
2420
+ static defaultAttributes = {
2421
+ coverEnable: false,
2422
+ spaceWidth: 5,
2423
+ layoutArcGap: 6,
2424
+ textStyle: {
2425
+ visible: true,
2426
+ fontSize: 14,
2427
+ fontWeight: 'normal',
2428
+ fillOpacity: 1
2429
+ },
2430
+ position: 'outside',
2431
+ offset: 0,
2432
+ line: {
2433
+ visible: true,
2434
+ line1MinLength: 20,
2435
+ line2MinLength: 10
2436
+ },
2437
+ layout: {
2438
+ align: 'arc',
2439
+ strategy: 'priority',
2440
+ tangentConstraint: true
2441
+ }
2442
+ };
2443
+ _ellipsisWidth = 0;
2444
+ _arcLeft = new Map();
2445
+ _arcRight = new Map();
2446
+ constructor(attributes) {
2447
+ super(vutils.merge({}, ArcLabel.defaultAttributes, attributes));
2448
+ }
2449
+ labeling(textBounds, graphicBounds, position = 'outside', offset = 0, graphicAttributes, textData, width, height, attribute) {
2450
+ if (!textBounds || !graphicBounds) {
2451
+ return;
2452
+ }
2453
+ const radiusRatio = this.computeLayoutOuterRadius(graphicAttributes.outerRadius, width, height);
2454
+ const radius = this.computeRadius(radiusRatio, width, height);
2455
+ const center = { x: graphicAttributes?.x ?? 0, y: graphicAttributes?.y ?? 0 };
2456
+ const item = textData;
2457
+ const arcMiddleAngle = (graphicAttributes.startAngle + graphicAttributes.endAngle) / 2;
2458
+ const intervalAngle = graphicAttributes.endAngle - graphicAttributes.startAngle;
2459
+ const arcQuadrant = computeQuadrant(graphicAttributes.endAngle - intervalAngle / 2);
2460
+ const arcMiddle = circlePoint(center.x, center.y, graphicAttributes.outerRadius, arcMiddleAngle);
2461
+ const outerArcMiddle = circlePoint(center.x, center.y, radius + attribute.line.line1MinLength, arcMiddleAngle);
2462
+ const arc = new ArcInfo(item, arcMiddle, outerArcMiddle, arcQuadrant, intervalAngle, arcMiddleAngle);
2463
+ arc.pointA = circlePoint(center.x, center.y, this.computeDatumRadius(center.x * 2, center.y * 2, graphicAttributes.outerRadius), arc.middleAngle);
2464
+ arc.labelSize = {
2465
+ width: textBounds.x2 - textBounds.x1,
2466
+ height: textBounds.y2 - textBounds.y1
2467
+ };
2468
+ if (isQuadrantRight(arc.quadrant)) {
2469
+ arc.textAlign = 'left';
2470
+ arc.textBaseline = 'middle';
2471
+ this._arcRight.set(arc.refDatum, arc);
2472
+ }
2473
+ else if (isQuadrantLeft(arc.quadrant)) {
2474
+ arc.textAlign = 'right';
2475
+ arc.textBaseline = 'middle';
2476
+ this._arcLeft.set(arc.refDatum, arc);
2477
+ }
2478
+ }
2479
+ layoutArcLabels(position, attribute, currentMarks) {
2480
+ const leftArcs = Array.from(this._arcLeft.values());
2481
+ const rightArcs = Array.from(this._arcRight.values());
2482
+ const arcs = [];
2483
+ if (position === 'inside') {
2484
+ arcs.push(...this._layoutInsideLabels(rightArcs, attribute, currentMarks));
2485
+ arcs.push(...this._layoutInsideLabels(leftArcs, attribute, currentMarks));
2486
+ }
2487
+ else {
2488
+ arcs.push(...this._layoutOutsideLabels(rightArcs, attribute, currentMarks));
2489
+ arcs.push(...this._layoutOutsideLabels(leftArcs, attribute, currentMarks));
2490
+ }
2491
+ return arcs;
2492
+ }
2493
+ _layoutInsideLabels(arcs, attribute, currentMarks) {
2494
+ const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
2495
+ const innerRadiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.innerRadius, attribute.width, attribute.height);
2496
+ const outerRadiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
2497
+ const labelConfig = attribute;
2498
+ const spaceWidth = labelConfig.spaceWidth;
2499
+ arcs.forEach((arc) => {
2500
+ const { labelSize, radian } = arc;
2501
+ const innerRadius = this.computeRadius(innerRadiusRatio, attribute.width, attribute.height, 1);
2502
+ const outerRadius = this.computeRadius(outerRadiusRatio, attribute.width, attribute.height, 1);
2503
+ const minRadian = connectLineRadian(outerRadius, labelSize.height);
2504
+ let limit;
2505
+ if (radian < minRadian) {
2506
+ limit = 0;
2507
+ }
2508
+ else {
2509
+ let minRadius;
2510
+ if (radian >= Math.PI) {
2511
+ minRadius = innerRadius;
2512
+ }
2513
+ else {
2514
+ minRadius = Math.max(innerRadius, labelSize.height / 2 / Math.tan(radian / 2));
2515
+ }
2516
+ limit = outerRadius - minRadius - spaceWidth;
2517
+ }
2518
+ if (labelConfig?.rotate !== true) {
2519
+ limit = outerRadius - spaceWidth;
2520
+ }
2521
+ const text = this._getFormatLabelText(arc.refDatum, limit);
2522
+ arc.labelText = text;
2523
+ const labelWidth = Math.min(limit, arc.labelSize.width);
2524
+ const align = this._computeAlign(arc, attribute);
2525
+ const alignOffset = align === 'left' ? labelWidth : align === 'right' ? 0 : labelWidth / 2;
2526
+ const labelRadius = outerRadius - spaceWidth - alignOffset;
2527
+ arc.labelPosition = circlePoint(center.x, center.y, labelRadius, arc.middleAngle);
2528
+ arc.labelLimit = labelWidth;
2529
+ if (!vutils.isGreater(labelWidth, 0)) {
2530
+ arc.labelVisible = false;
2531
+ }
2532
+ (arc.textAlign = 'center'), (arc.textBaseline = 'middle');
2533
+ arc.angle = arc.middleAngle;
2534
+ });
2535
+ return arcs;
2536
+ }
2537
+ _layoutOutsideLabels(arcs, attribute, currentMarks) {
2538
+ const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
2539
+ const height = center.y * 2;
2540
+ const line2MinLength = attribute.line.line2MinLength;
2541
+ const labelLayout = attribute.layout;
2542
+ const spaceWidth = attribute.spaceWidth;
2543
+ arcs.forEach(arc => {
2544
+ const direction = isQuadrantLeft(arc.quadrant) ? -1 : 1;
2545
+ arc.labelPosition = {
2546
+ x: arc.outerCenter.x + direction * (arc.labelSize.width / 2 + line2MinLength + spaceWidth),
2547
+ y: arc.outerCenter.y
2548
+ };
2549
+ });
2550
+ arcs.sort((a, b) => {
2551
+ return a.labelPosition.y - b.labelPosition.y;
2552
+ });
2553
+ if (attribute.coverEnable !== false || labelLayout.strategy === 'none') {
2554
+ for (const arc of arcs) {
2555
+ const { labelPosition, labelSize } = arc;
2556
+ arc.labelLimit = labelSize.width;
2557
+ arc.pointB = isQuadrantLeft(arc.quadrant)
2558
+ ? {
2559
+ x: labelPosition.x + labelSize.width / 2 + line2MinLength + spaceWidth,
2560
+ y: labelPosition.y
2561
+ }
2562
+ : {
2563
+ x: labelPosition.x - labelSize.width / 2 - line2MinLength - spaceWidth,
2564
+ y: labelPosition.y
2565
+ };
2566
+ this._computeX(arc, attribute, currentMarks);
2567
+ }
2568
+ if (attribute.coverEnable === false && labelLayout.strategy === 'none') {
2569
+ this._coverLabels(arcs);
2570
+ }
2571
+ }
2572
+ else {
2573
+ const maxLabels = height / (attribute.textStyle?.fontSize || 16);
2574
+ this._adjustY(arcs, maxLabels, attribute, currentMarks);
2575
+ const { minY, maxY } = arcs.reduce((yInfo, arc) => {
2576
+ const { y1, y2 } = arc.getLabelBounds();
2577
+ yInfo.minY = Math.max(0, Math.min(y1, yInfo.minY));
2578
+ yInfo.maxY = Math.min(height, Math.max(y2, yInfo.maxY));
2579
+ return yInfo;
2580
+ }, { minY: Infinity, maxY: -Infinity });
2581
+ const halfY = Math.max(Math.abs(height / 2 - minY), Math.abs(maxY - height / 2));
2582
+ const r = this._computeLayoutRadius(halfY, attribute, currentMarks);
2583
+ for (const arc of arcs) {
2584
+ this._computePointB(arc, r, attribute, currentMarks);
2585
+ this._computeX(arc, attribute, currentMarks);
2586
+ }
2587
+ }
2588
+ const width = center.x * 2;
2589
+ arcs.forEach(arc => {
2590
+ if (arc.labelVisible &&
2591
+ (vutils.isLess(arc.pointB.x, line2MinLength + spaceWidth) ||
2592
+ vutils.isGreater(arc.pointB.x, width - line2MinLength - spaceWidth))) {
2593
+ arc.labelVisible = false;
2594
+ }
2595
+ arc.angle = 0;
2596
+ });
2597
+ return arcs;
2598
+ }
2599
+ _computeX(arc, attribute, currentMarks) {
2600
+ const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
2601
+ const plotLayout = { width: center.x * 2, height: center.y * 2 };
2602
+ const radiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
2603
+ const line1MinLength = attribute.line.line1MinLength;
2604
+ const line2MinLength = attribute.line.line2MinLength;
2605
+ const labelLayoutAlign = attribute.layout?.align;
2606
+ const spaceWidth = attribute.spaceWidth;
2607
+ const align = this._computeAlign(arc, attribute);
2608
+ const { labelPosition, quadrant, pointB } = arc;
2609
+ if (!vutils.isValidNumber(pointB.x * pointB.y)) {
2610
+ arc.pointC = { x: NaN, y: NaN };
2611
+ labelPosition.x = NaN;
2612
+ arc.labelLimit = 0;
2613
+ }
2614
+ const radius = this.computeRadius(radiusRatio, attribute.width, attribute.height);
2615
+ const flag = isQuadrantLeft(quadrant) ? -1 : 1;
2616
+ let cx = 0;
2617
+ const restWidth = flag > 0 ? plotLayout.width - pointB.x : pointB.x;
2618
+ let limit = restWidth - line2MinLength - spaceWidth;
2619
+ if (labelLayoutAlign === 'labelLine') {
2620
+ cx = (radius + line1MinLength + line2MinLength) * flag + center.x;
2621
+ limit = (flag > 0 ? plotLayout.width - cx : cx) - spaceWidth;
2622
+ }
2623
+ const text = this._getFormatLabelText(arc.refDatum, limit);
2624
+ arc.labelText = text;
2625
+ let labelWidth = Math.min(limit, arc.labelSize.width);
2626
+ switch (labelLayoutAlign) {
2627
+ case 'labelLine':
2628
+ break;
2629
+ case 'edge':
2630
+ cx = flag > 0 ? plotLayout.width - labelWidth - spaceWidth : labelWidth + spaceWidth;
2631
+ break;
2632
+ case 'arc':
2633
+ default:
2634
+ cx = pointB.x + flag * line2MinLength;
2635
+ break;
2636
+ }
2637
+ labelWidth = Math.max(this._ellipsisWidth, labelWidth);
2638
+ arc.pointC = { x: cx, y: labelPosition.y };
2639
+ if (labelLayoutAlign === 'edge') {
2640
+ const alignOffset = this._computeAlignOffset(align, labelWidth, -flag);
2641
+ labelPosition.x = flag > 0 ? plotLayout.width + alignOffset : alignOffset;
2642
+ }
2643
+ else {
2644
+ const alignOffset = this._computeAlignOffset(align, labelWidth, flag);
2645
+ labelPosition.x = cx + alignOffset + flag * spaceWidth;
2646
+ }
2647
+ arc.labelLimit = labelWidth;
2648
+ }
2649
+ _computeAlignOffset(align, labelWidth, alignFlag) {
2650
+ switch (align) {
2651
+ case 'left':
2652
+ return alignFlag < 0 ? -labelWidth : 0;
2653
+ case 'right':
2654
+ return alignFlag < 0 ? 0 : labelWidth;
2655
+ case 'center':
2656
+ default:
2657
+ return (labelWidth / 2) * alignFlag;
2658
+ }
2659
+ }
2660
+ _computeAlign(arc, attribute) {
2661
+ const labelConfig = attribute;
2662
+ const textAlign = labelConfig.textStyle?.textAlign ?? labelConfig.textStyle?.align;
2663
+ const layoutAlign = labelConfig.layout?.textAlign ?? labelConfig.layout?.align;
2664
+ if (labelConfig.position !== 'inside') {
2665
+ if (vutils.isNil(textAlign) || textAlign === 'auto') {
2666
+ if (layoutAlign === 'edge') {
2667
+ return isQuadrantLeft(arc.quadrant) ? 'left' : 'right';
2668
+ }
2669
+ return isQuadrantLeft(arc.quadrant) ? 'right' : 'left';
2670
+ }
2671
+ return textAlign;
2672
+ }
2673
+ return vutils.isNil(textAlign) || textAlign === 'auto' ? 'center' : textAlign;
2674
+ }
2675
+ _getFormatLabelText(value, limit) {
2676
+ return value.text;
2677
+ }
2678
+ _adjustY(arcs, maxLabels, attribute, currentMarks) {
2679
+ const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
2680
+ const plotRect = { width: center.x * 2, height: center.y * 2 };
2681
+ const labelLayout = attribute.layout;
2682
+ if (labelLayout.strategy === 'vertical') {
2683
+ let lastY = 0;
2684
+ let delta;
2685
+ const len = arcs.length;
2686
+ if (len <= 0) {
2687
+ return;
2688
+ }
2689
+ for (let i = 0; i < len; i++) {
2690
+ const { y1 } = arcs[i].getLabelBounds();
2691
+ delta = y1 - lastY;
2692
+ if (vutils.isLess(delta, 0)) {
2693
+ const index = this._shiftY(arcs, i, len - 1, -delta);
2694
+ this._shiftY(arcs, index, 0, delta / 2);
2695
+ }
2696
+ const { y2 } = arcs[i].getLabelBounds();
2697
+ lastY = y2;
2698
+ }
2699
+ const { y1: firstY1 } = arcs[0].getLabelBounds();
2700
+ delta = firstY1 - 0;
2701
+ if (vutils.isLess(delta, 0)) {
2702
+ this._shiftY(arcs, 0, len - 1, -delta);
2703
+ }
2704
+ for (let i = arcs.length - 1; i >= 0; i--) {
2705
+ if (arcs[i].getLabelBounds().y2 > plotRect.height) {
2706
+ arcs[i].labelVisible = false;
2707
+ }
2708
+ else {
2709
+ break;
2710
+ }
2711
+ }
2712
+ }
2713
+ else if (labelLayout.strategy !== 'none') {
2714
+ const priorityArcs = arcs.map((arc, i) => {
2715
+ return {
2716
+ arc,
2717
+ originIndex: i,
2718
+ priorityIndex: 0
2719
+ };
2720
+ });
2721
+ priorityArcs.sort((a, b) => {
2722
+ return b.arc.radian - a.arc.radian;
2723
+ });
2724
+ priorityArcs.forEach((priorityArc, i) => {
2725
+ priorityArc.priorityIndex = i;
2726
+ priorityArc.arc.labelVisible = false;
2727
+ });
2728
+ let topLabelIndex = Infinity;
2729
+ let bottomLabelIndex = -Infinity;
2730
+ for (let i = 0; i < maxLabels && i < arcs.length; i++) {
2731
+ this._storeY(arcs);
2732
+ const arc = priorityArcs[i].arc;
2733
+ this._computeYRange(arc, attribute, currentMarks);
2734
+ arc.labelVisible = true;
2735
+ const curY = arc.labelPosition.y;
2736
+ const { lastIndex, nextIndex } = this._findNeighborIndex(arcs, priorityArcs[i]);
2737
+ const lastArc = arcs[lastIndex];
2738
+ const nextArc = arcs[nextIndex];
2739
+ if (lastIndex === -1 && nextIndex !== -1) {
2740
+ const nextY = nextArc.labelPosition.y;
2741
+ if (curY > nextY) {
2742
+ arc.labelPosition.y = nextY - nextArc.labelSize.height / 2 - arc.labelSize.height / 2;
2743
+ }
2744
+ else {
2745
+ this._twoWayShift(arcs, arc, nextArc, nextIndex);
2746
+ }
2747
+ }
2748
+ else if (lastIndex !== -1 && nextIndex === -1) {
2749
+ const lastY = lastArc.labelPosition.y;
2750
+ if (curY < lastY) {
2751
+ arc.labelPosition.y = lastY + lastArc.labelSize.height / 2 + arc.labelSize.height / 2;
2752
+ }
2753
+ else {
2754
+ this._twoWayShift(arcs, lastArc, arc, priorityArcs[i].originIndex);
2755
+ }
2756
+ }
2757
+ else if (lastIndex !== -1 && nextIndex !== -1) {
2758
+ const lastY = lastArc.labelPosition.y;
2759
+ const nextY = nextArc.labelPosition.y;
2760
+ if (curY > nextY) {
2761
+ arc.labelPosition.y = nextY - nextArc.labelSize.height / 2 - arc.labelSize.height / 2;
2762
+ this._twoWayShift(arcs, lastArc, arc, priorityArcs[i].originIndex);
2763
+ }
2764
+ else if (curY < lastY) {
2765
+ arc.labelPosition.y = lastY + lastArc.labelSize.height / 2 + arc.labelSize.height / 2;
2766
+ this._twoWayShift(arcs, arc, nextArc, nextIndex);
2767
+ }
2768
+ else {
2769
+ this._twoWayShift(arcs, lastArc, arc, priorityArcs[i].originIndex);
2770
+ this._twoWayShift(arcs, arc, nextArc, nextIndex);
2771
+ }
2772
+ }
2773
+ const nextTopIndex = Math.min(topLabelIndex, priorityArcs[i].originIndex);
2774
+ const nextBottomIndex = Math.max(bottomLabelIndex, priorityArcs[i].originIndex);
2775
+ let delta;
2776
+ delta = arcs[nextBottomIndex].getLabelBounds().y2 - plotRect.height;
2777
+ if (vutils.isGreater(delta, 0)) {
2778
+ this._shiftY(arcs, nextBottomIndex, 0, -delta);
2779
+ }
2780
+ delta = arcs[nextTopIndex].getLabelBounds().y1 - 0;
2781
+ if (vutils.isLess(delta, 0)) {
2782
+ this._shiftY(arcs, nextTopIndex, arcs.length - 1, -delta);
2783
+ }
2784
+ delta = arcs[nextBottomIndex].getLabelBounds().y2 - plotRect.height;
2785
+ if (vutils.isGreater(delta, 0)) {
2786
+ arc.labelVisible = false;
2787
+ this._restoreY(arcs);
2788
+ break;
2789
+ }
2790
+ else if (labelLayout.tangentConstraint && !this._checkYRange(arcs)) {
2791
+ arc.labelVisible = false;
2792
+ this._restoreY(arcs);
2793
+ }
2794
+ else {
2795
+ topLabelIndex = nextTopIndex;
2796
+ bottomLabelIndex = nextBottomIndex;
2797
+ }
2798
+ }
2799
+ }
2800
+ }
2801
+ _shiftY(arcs, start, end, delta) {
2802
+ const direction = start < end ? 1 : -1;
2803
+ let index = start;
2804
+ while (index !== -1) {
2805
+ arcs[index].labelPosition.y += delta;
2806
+ const nextIndex = this._findNextVisibleIndex(arcs, index, end, direction);
2807
+ if (nextIndex >= 0 && nextIndex < arcs.length) {
2808
+ const { y1: curY1, y2: curY2 } = arcs[index].getLabelBounds();
2809
+ const { y1: nextY1, y2: nextY2 } = arcs[nextIndex].getLabelBounds();
2810
+ if ((direction > 0 && curY2 < nextY1) || (direction < 0 && curY1 > nextY2)) {
2811
+ return index;
2812
+ }
2813
+ }
2814
+ index = nextIndex;
2815
+ }
2816
+ return end;
2817
+ }
2818
+ _findNextVisibleIndex(arcs, start, end, direction) {
2819
+ const diff = (end - start) * direction;
2820
+ for (let i = 1; i <= diff; i++) {
2821
+ const index = start + i * direction;
2822
+ if (arcs[index].labelVisible) {
2823
+ return index;
2824
+ }
2825
+ }
2826
+ return -1;
2827
+ }
2828
+ _computePointB(arc, r, attribute, currentMarks) {
2829
+ const labelConfig = attribute;
2830
+ const radiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
2831
+ const line1MinLength = labelConfig.line.line1MinLength;
2832
+ const labelLayout = labelConfig.layout;
2833
+ if (labelLayout.strategy === 'none') {
2834
+ arc.pointB = {
2835
+ x: arc.outerCenter.x,
2836
+ y: arc.outerCenter.y
2837
+ };
2838
+ }
2839
+ else {
2840
+ const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
2841
+ const radius = this.computeRadius(radiusRatio, attribute.width, attribute.height);
2842
+ const { labelPosition, quadrant } = arc;
2843
+ const outerR = Math.max(radius + line1MinLength, currentMarks[0].attribute.outerRadius);
2844
+ const rd = r - outerR;
2845
+ const x = Math.sqrt(r ** 2 - Math.abs(center.y - labelPosition.y) ** 2) - rd;
2846
+ if (vutils.isValidNumber(x)) {
2847
+ arc.pointB = {
2848
+ x: center.x + x * (isQuadrantLeft(quadrant) ? -1 : 1),
2849
+ y: labelPosition.y
2850
+ };
2851
+ }
2852
+ else {
2853
+ arc.pointB = { x: NaN, y: NaN };
2854
+ }
2855
+ }
2856
+ }
2857
+ _storeY(arcs) {
2858
+ for (const arc of arcs) {
2859
+ if (arc.labelVisible) {
2860
+ arc.lastLabelY = arc.labelPosition.y;
2861
+ }
2862
+ }
2863
+ }
2864
+ _computeYRange(arc, attribute, currentMarks) {
2865
+ const center = { x: currentMarks[0].attribute?.x ?? 0, y: currentMarks[0].attribute?.y ?? 0 };
2866
+ const plotRect = { width: center.x * 2, height: center.y * 2 };
2867
+ const radiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
2868
+ const line1MinLength = attribute.line.line1MinLength;
2869
+ const { width, height } = plotRect;
2870
+ const radius = this.computeRadius(radiusRatio, attribute.width, attribute.height);
2871
+ const r = this._computeLayoutRadius(height / 2, attribute, currentMarks);
2872
+ const cx = Math.abs(arc.center.x - width / 2);
2873
+ const cy = arc.center.y - height / 2;
2874
+ let a;
2875
+ let b;
2876
+ let c;
2877
+ if (vutils.isNumberClose(width / 2, cx)) {
2878
+ a = 0;
2879
+ b = 1;
2880
+ c = -cy;
2881
+ }
2882
+ else if (vutils.isNumberClose(height / 2, cy)) {
2883
+ a = 1;
2884
+ b = 0;
2885
+ c = -cx;
2886
+ }
2887
+ else {
2888
+ const k = -1 / (cy / cx);
2889
+ a = k;
2890
+ b = -1;
2891
+ c = cy - k * cx;
2892
+ }
2893
+ const points = lineCirclePoints(a, b, c, line1MinLength + radius - r, 0, r);
2894
+ if (points.length < 2) {
2895
+ return;
2896
+ }
2897
+ let min;
2898
+ let max;
2899
+ if (points[0].x > points[1].x) {
2900
+ points.reverse();
2901
+ }
2902
+ if (points[0].x < 0) {
2903
+ if (vutils.isNumberClose(points[0].y, points[1].y)) {
2904
+ if (Math.abs(arc.middleAngle) < Math.PI / 2) {
2905
+ min = 0;
2906
+ max = points[1].y + height / 2;
2907
+ }
2908
+ else {
2909
+ min = points[1].y + height / 2;
2910
+ max = height;
2911
+ }
2912
+ }
2913
+ else if (points[0].y < points[1].y) {
2914
+ min = 0;
2915
+ max = points[1].y + height / 2;
2916
+ }
2917
+ else {
2918
+ min = points[1].y + height / 2;
2919
+ max = plotRect.height;
2920
+ }
2921
+ }
2922
+ else {
2923
+ min = Math.min(points[0].y, points[1].y) + height / 2;
2924
+ max = Math.max(points[0].y, points[1].y) + height / 2;
2925
+ }
2926
+ arc.labelYRange = [min, max];
2927
+ }
2928
+ _computeLayoutRadius(halfYLength, attribute, currentMarks) {
2929
+ const labelConfig = attribute;
2930
+ const layoutArcGap = labelConfig.layoutArcGap;
2931
+ const line1MinLength = labelConfig.line.line1MinLength;
2932
+ const radiusRatio = this.computeLayoutOuterRadius(currentMarks[0].attribute.outerRadius, attribute.width, attribute.height);
2933
+ const radius = this.computeRadius(radiusRatio, attribute.width, attribute.height);
2934
+ const outerR = radius + line1MinLength;
2935
+ const a = outerR - layoutArcGap;
2936
+ return Math.max((a ** 2 + halfYLength ** 2) / (2 * a), outerR);
2937
+ }
2938
+ _findNeighborIndex(arcs, priorityArc) {
2939
+ const index = priorityArc.originIndex;
2940
+ let lastIndex = -1;
2941
+ let nextIndex = -1;
2942
+ for (let i = index - 1; i >= 0; i--) {
2943
+ if (arcs[i].labelVisible) {
2944
+ lastIndex = i;
2945
+ break;
2946
+ }
2947
+ }
2948
+ for (let i = index + 1; i < arcs.length; i++) {
2949
+ if (arcs[i].labelVisible) {
2950
+ nextIndex = i;
2951
+ break;
2952
+ }
2953
+ }
2954
+ return {
2955
+ lastIndex,
2956
+ nextIndex
2957
+ };
2958
+ }
2959
+ _twoWayShift(arcs, lastArc, nextArc, nextIndex) {
2960
+ const delta = nextArc.getLabelBounds().y1 - lastArc.getLabelBounds().y2;
2961
+ if (vutils.isLess(delta, 0)) {
2962
+ const i = this._shiftY(arcs, nextIndex, arcs.length - 1, -delta);
2963
+ this._shiftY(arcs, i, 0, delta / 2);
2964
+ }
2965
+ }
2966
+ _restoreY(arcs) {
2967
+ for (const arc of arcs) {
2968
+ if (arc.labelVisible) {
2969
+ arc.labelPosition.y = arc.lastLabelY;
2970
+ }
2971
+ }
2972
+ }
2973
+ _checkYRange(arcs) {
2974
+ for (const arc of arcs) {
2975
+ const { labelYRange, labelPosition } = arc;
2976
+ if (arc.labelVisible &&
2977
+ labelYRange &&
2978
+ (vutils.isLess(labelPosition.y, labelYRange[0]) || vutils.isGreater(labelPosition.y, labelYRange[1]))) {
2979
+ return false;
2980
+ }
2981
+ }
2982
+ return true;
2983
+ }
2984
+ _coverLabels(arcs) {
2985
+ if (arcs.length <= 1) {
2986
+ return;
2987
+ }
2988
+ let lastBounds = arcs[0].getLabelBounds();
2989
+ for (let i = 1; i < arcs.length; i++) {
2990
+ const bounds = arcs[i].getLabelBounds();
2991
+ if (!checkBoundsOverlap(lastBounds, bounds)) {
2992
+ lastBounds = bounds;
2993
+ }
2994
+ else {
2995
+ arcs[i].labelVisible = false;
2996
+ }
2997
+ }
2998
+ }
2999
+ computeRadius(r, width, height, k) {
3000
+ return this.computeLayoutRadius(width ? width : 0, height ? height : 0) * r * (vutils.isNil(k) ? 1 : k);
3001
+ }
3002
+ computeLayoutRadius(width, height) {
3003
+ return Math.min(width / 2, height / 2);
3004
+ }
3005
+ computeLayoutOuterRadius(r, width, height) {
3006
+ return r / (Math.min(width, height) / 2);
3007
+ }
3008
+ computeDatumRadius(width, height, outerRadius) {
3009
+ const outerRadiusRatio = this.computeLayoutOuterRadius(outerRadius, width, height);
3010
+ return this.computeLayoutRadius(width ? width : 0, height ? height : 0) * outerRadiusRatio;
3011
+ }
3012
+ }
3013
+
2225
3014
  const labelComponentMap = {
2226
3015
  rect: RectLabel,
2227
- symbol: SymbolLabel
3016
+ symbol: SymbolLabel,
3017
+ arc: ArcLabel
2228
3018
  };
2229
3019
  class DataLabel extends AbstractComponent {
2230
3020
  name = 'data-label';
@@ -9621,9 +10411,11 @@
9621
10411
  }
9622
10412
  }
9623
10413
 
9624
- const version = "0.13.9-alpha.1";
10414
+ const version = "0.13.9-alpha.5";
9625
10415
 
9626
10416
  exports.AbstractComponent = AbstractComponent;
10417
+ exports.ArcInfo = ArcInfo;
10418
+ exports.ArcLabel = ArcLabel;
9627
10419
  exports.BasePlayer = BasePlayer;
9628
10420
  exports.Brush = Brush;
9629
10421
  exports.CircleAxis = CircleAxis;