@visactor/vrender-components 0.13.7 → 0.13.8-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) 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/base.d.ts +12 -11
  5. package/cjs/label/base.js +83 -62
  6. package/cjs/label/base.js.map +1 -1
  7. package/cjs/label/overlap/place.d.ts +8 -4
  8. package/cjs/label/overlap/place.js +14 -2
  9. package/cjs/label/overlap/place.js.map +1 -1
  10. package/cjs/label/rect.d.ts +5 -3
  11. package/cjs/label/rect.js.map +1 -1
  12. package/cjs/label/symbol.d.ts +5 -3
  13. package/cjs/label/symbol.js.map +1 -1
  14. package/cjs/label/type.d.ts +12 -7
  15. package/cjs/label/type.js.map +1 -1
  16. package/cjs/segment/segment.js +4 -1
  17. package/cjs/segment/segment.js.map +1 -1
  18. package/cjs/segment/type.d.ts +1 -0
  19. package/cjs/segment/type.js.map +1 -1
  20. package/cjs/util/common.d.ts +3 -1
  21. package/cjs/util/common.js +14 -2
  22. package/cjs/util/common.js.map +1 -1
  23. package/dist/index.js +170 -86
  24. package/dist/index.min.js +1 -1
  25. package/es/index.d.ts +1 -1
  26. package/es/index.js +1 -1
  27. package/es/index.js.map +1 -1
  28. package/es/label/base.d.ts +12 -11
  29. package/es/label/base.js +85 -65
  30. package/es/label/base.js.map +1 -1
  31. package/es/label/overlap/place.d.ts +8 -4
  32. package/es/label/overlap/place.js +11 -0
  33. package/es/label/overlap/place.js.map +1 -1
  34. package/es/label/rect.d.ts +5 -3
  35. package/es/label/rect.js.map +1 -1
  36. package/es/label/symbol.d.ts +5 -3
  37. package/es/label/symbol.js.map +1 -1
  38. package/es/label/type.d.ts +12 -7
  39. package/es/label/type.js.map +1 -1
  40. package/es/segment/segment.js +4 -1
  41. package/es/segment/segment.js.map +1 -1
  42. package/es/segment/type.d.ts +1 -0
  43. package/es/segment/type.js.map +1 -1
  44. package/es/util/common.d.ts +3 -1
  45. package/es/util/common.js +12 -0
  46. package/es/util/common.js.map +1 -1
  47. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -341,6 +341,26 @@
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
+ }
344
364
 
345
365
  const defaultAlternativeColors = ['#ffffff', '#000000'];
346
366
  function labelSmartInvert(foregroundColorOrigin, backgroundColorOrogin, textType, contrastRatiosThreshold, alternativeColors) {
@@ -1514,6 +1534,28 @@
1514
1534
  return DefaultPositions;
1515
1535
  }
1516
1536
  }
1537
+ function clampText(text, width, height) {
1538
+ const { x1, x2, y1, y2 } = text.AABBBounds;
1539
+ const minX = Math.min(x1, x2);
1540
+ const maxX = Math.max(x1, x2);
1541
+ const minY = Math.min(y1, y2);
1542
+ const maxY = Math.max(y1, y2);
1543
+ let dx = 0;
1544
+ let dy = 0;
1545
+ if (minX < 0 && maxX - minX <= width) {
1546
+ dx = -minX;
1547
+ }
1548
+ else if (maxX > width && minX - (maxX - width) >= 0) {
1549
+ dx = width - maxX;
1550
+ }
1551
+ if (minY < 0 && maxY - minY <= height) {
1552
+ dy = -minY;
1553
+ }
1554
+ else if (maxY > height && minY - (maxY - height) >= 0) {
1555
+ dy = height - maxY;
1556
+ }
1557
+ return { dx, dy };
1558
+ }
1517
1559
 
1518
1560
  const fadeIn = (textAttribute = {}) => {
1519
1561
  return {
@@ -1564,17 +1606,37 @@
1564
1606
  setBitmapTool(bmpTool) {
1565
1607
  this._bmpTool = bmpTool;
1566
1608
  }
1567
- _relationMap;
1568
- _prevRelationMap;
1569
- _textMap;
1609
+ _graphicToText;
1610
+ _idToGraphic;
1570
1611
  onAfterLabelOverlap;
1571
1612
  _lastHover;
1572
1613
  _lastSelect;
1573
1614
  _enableAnimation;
1574
1615
  render() {
1575
- const currentBaseMarks = this._checkMarks();
1576
- const labels = this.layout(currentBaseMarks);
1577
- this._smartInvert(labels);
1616
+ this._prepare();
1617
+ const { overlap, smartInvert, dataFilter, customLayoutFunc, customOverlapFunc } = this.attribute;
1618
+ let data = this.attribute.data;
1619
+ if (vutils.isFunction(dataFilter)) {
1620
+ data = dataFilter(data);
1621
+ }
1622
+ let labels;
1623
+ if (vutils.isFunction(customLayoutFunc)) {
1624
+ labels = customLayoutFunc(data, (d) => this._idToGraphic.get(d.id));
1625
+ }
1626
+ else {
1627
+ 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);
1634
+ }
1635
+ }
1636
+ }
1637
+ if (smartInvert !== false) {
1638
+ this._smartInvert(labels);
1639
+ }
1578
1640
  this._renderLabels(labels);
1579
1641
  }
1580
1642
  _bindEvent(target) {
@@ -1651,67 +1713,66 @@
1651
1713
  this._setStates(text);
1652
1714
  return text;
1653
1715
  }
1654
- _checkMarks() {
1655
- const baseMarks = this.getBaseMarks();
1716
+ _prepare() {
1717
+ const baseMarks = getMarksByName(this.getRootNode(), this.attribute.baseMarkGroupName);
1656
1718
  const currentBaseMarks = [];
1657
1719
  baseMarks.forEach(mark => {
1658
1720
  if (mark.releaseStatus !== 'willRelease') {
1659
1721
  currentBaseMarks.push(mark);
1660
1722
  }
1661
1723
  });
1662
- this._prevRelationMap = new Map(this._relationMap);
1663
- this._relationMap?.clear();
1664
- return currentBaseMarks;
1665
- }
1666
- layout(currentMarks) {
1667
- const { textStyle, position, offset } = this.attribute;
1668
- let { data } = this.attribute;
1669
- if (vutils.isFunction(data)) {
1670
- data = data({});
1724
+ this._idToGraphic?.clear();
1725
+ this._baseMarks = currentBaseMarks;
1726
+ if (!currentBaseMarks || currentBaseMarks.length === 0) {
1727
+ return;
1671
1728
  }
1729
+ const { data } = this.attribute;
1672
1730
  if (!data || data.length === 0) {
1673
- return [];
1731
+ return;
1674
1732
  }
1675
- let labels = [];
1676
- if (vutils.isFunction(this.attribute.sort) && currentMarks && currentMarks.length) {
1677
- currentMarks = currentMarks.sort(this.attribute.sort);
1733
+ if (!this._idToGraphic) {
1734
+ this._idToGraphic = new Map();
1678
1735
  }
1679
- if (!this._relationMap) {
1680
- this._relationMap = new Map();
1736
+ for (let i = 0; i < currentBaseMarks.length; i++) {
1737
+ const textData = data[i];
1738
+ const baseMark = currentBaseMarks[i];
1739
+ if (textData && baseMark) {
1740
+ if (!vutils.isValid(textData.id)) {
1741
+ textData.id = `vrender-component-${this.name}-${i}`;
1742
+ }
1743
+ this._idToGraphic.set(textData.id, baseMark);
1744
+ }
1681
1745
  }
1746
+ }
1747
+ layout(data = []) {
1748
+ const { textStyle = {}, position, offset } = this.attribute;
1749
+ const labels = [];
1682
1750
  for (let i = 0; i < data.length; i++) {
1683
1751
  const textData = data[i];
1684
- const baseMark = currentMarks?.[i];
1752
+ const baseMark = this._idToGraphic.get(textData.id);
1685
1753
  const labelAttribute = {
1686
1754
  ...textStyle,
1687
- ...textData,
1688
- _relatedIndex: i
1755
+ ...textData
1689
1756
  };
1690
- this._relationMap.set(i, baseMark);
1691
- if (textData) {
1692
- const text = vrender.createText(labelAttribute);
1693
- text.update();
1694
- const textBounds = this.getGraphicBounds(text);
1695
- const graphicBounds = this.getGraphicBounds(baseMark, { x: textData.x, y: textData.y });
1696
- const textAttributes = this.labeling(textBounds, graphicBounds, vutils.isFunction(position) ? position(textData) : position, offset);
1697
- if (!textAttributes) {
1698
- continue;
1699
- }
1700
- labelAttribute.x = textAttributes.x;
1701
- labelAttribute.y = textAttributes.y;
1702
- labels.push(labelAttribute);
1757
+ const text = this._createLabelText(labelAttribute);
1758
+ const textBounds = this.getGraphicBounds(text);
1759
+ 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;
1703
1763
  }
1704
- }
1705
- this._baseMarks = currentMarks;
1706
- if (this.attribute.overlap !== false) {
1707
- labels = this.overlapping(labels, this.attribute.overlap);
1764
+ labelAttribute.x = textLocation.x;
1765
+ labelAttribute.y = textLocation.y;
1766
+ text.setAttributes(textLocation);
1767
+ labels.push(text);
1708
1768
  }
1709
1769
  return labels;
1710
1770
  }
1711
- overlapping(labels, option = {}) {
1771
+ _overlapping(labels) {
1712
1772
  if (labels.length === 0) {
1713
1773
  return [];
1714
1774
  }
1775
+ const option = this.attribute.overlap;
1715
1776
  const result = [];
1716
1777
  const baseMarkGroup = this.getBaseMarkGroup();
1717
1778
  const size = option.size ?? {
@@ -1721,7 +1782,7 @@
1721
1782
  if (size.width === 0 || size.height === 0) {
1722
1783
  return labels;
1723
1784
  }
1724
- const { avoidBaseMark, strategy = [], hideOnHit = true, clampForce = true } = option;
1785
+ const { avoidBaseMark, strategy = [], hideOnHit = true, clampForce = true, avoidMarks = [] } = option;
1725
1786
  const bmpTool = this._bmpTool || bitmapTool(size.width, size.height);
1726
1787
  const bitmap = this._bitmap || bmpTool.bitmap();
1727
1788
  const checkBounds = strategy.some(s => s.type === 'bound');
@@ -1730,22 +1791,34 @@
1730
1791
  mark.AABBBounds && bitmap.setRange(boundToRange(bmpTool, mark.AABBBounds, true));
1731
1792
  });
1732
1793
  }
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
+ }
1733
1806
  for (let i = 0; i < labels.length; i++) {
1734
1807
  if (labels[i].visible === false) {
1735
1808
  continue;
1736
1809
  }
1737
- const text = vrender.createText(labels[i]);
1738
- const baseMark = this._baseMarks?.[i];
1810
+ const text = labels[i];
1811
+ const baseMark = this._idToGraphic.get(text.attribute.id);
1739
1812
  text.update();
1740
1813
  if (canPlace(bmpTool, bitmap, text.AABBBounds, clampForce)) {
1741
1814
  if (!checkBounds) {
1742
1815
  bitmap.setRange(boundToRange(bmpTool, text.AABBBounds, true));
1743
- result.push({ ...text.attribute });
1816
+ result.push(text);
1744
1817
  continue;
1745
1818
  }
1746
1819
  if (checkBounds && baseMark?.AABBBounds && canPlaceInside(text.AABBBounds, baseMark?.AABBBounds)) {
1747
1820
  bitmap.setRange(boundToRange(bmpTool, text.AABBBounds, true));
1748
- result.push({ ...text.attribute });
1821
+ result.push(text);
1749
1822
  continue;
1750
1823
  }
1751
1824
  }
@@ -1753,28 +1826,33 @@
1753
1826
  for (let j = 0; j < strategy.length; j++) {
1754
1827
  hasPlace = place(bmpTool, bitmap, strategy[j], this.attribute, text, this.getGraphicBounds(baseMark, labels[i]), this.labeling);
1755
1828
  if (hasPlace !== false) {
1756
- result.push({
1757
- ...text.attribute,
1758
- x: hasPlace.x,
1759
- y: hasPlace.y
1760
- });
1829
+ text.setAttributes({ x: hasPlace.x, y: hasPlace.y });
1830
+ result.push(text);
1761
1831
  break;
1762
1832
  }
1763
1833
  }
1764
- !hasPlace && !hideOnHit && result.push({ ...text.attribute });
1834
+ if (!hasPlace && clampForce) {
1835
+ const { dx = 0, dy = 0 } = clampText(text, bmpTool.width, bmpTool.height);
1836
+ if (!(dx === 0 && dy === 0) &&
1837
+ canPlace(bmpTool, bitmap, {
1838
+ x1: text.AABBBounds.x1 + dx,
1839
+ x2: text.AABBBounds.x2 + dx,
1840
+ y1: text.AABBBounds.y1 + dy,
1841
+ y2: text.AABBBounds.y2 + dy
1842
+ })) {
1843
+ text.setAttributes({ x: text.attribute.x + dx, y: text.attribute.y + dy });
1844
+ bitmap.setRange(boundToRange(bmpTool, text.AABBBounds, true));
1845
+ result.push(text);
1846
+ continue;
1847
+ }
1848
+ }
1849
+ !hasPlace && !hideOnHit && result.push(text);
1765
1850
  }
1766
1851
  if (vutils.isFunction(this.onAfterLabelOverlap)) {
1767
1852
  this.onAfterLabelOverlap(bitmap);
1768
1853
  }
1769
1854
  return result;
1770
1855
  }
1771
- getBaseMarks() {
1772
- const baseMarkGroup = this.getBaseMarkGroup();
1773
- if (!baseMarkGroup) {
1774
- return;
1775
- }
1776
- return baseMarkGroup.getChildren();
1777
- }
1778
1856
  getBaseMarkGroup() {
1779
1857
  const { baseMarkGroupName } = this.attribute;
1780
1858
  if (!baseMarkGroupName) {
@@ -1799,17 +1877,16 @@
1799
1877
  const easing = animationConfig.easing ?? DefaultLabelAnimation.easing;
1800
1878
  const delay = animationConfig.delay ?? 0;
1801
1879
  const currentTextMap = new Map();
1802
- const prevTextMap = this._textMap || new Map();
1880
+ const prevTextMap = this._graphicToText || new Map();
1803
1881
  const texts = [];
1804
- labels.forEach((label, index) => {
1805
- const text = this._createLabelText(label);
1806
- const relatedGraphic = this._relationMap.get(label._relatedIndex);
1882
+ labels.forEach((text, index) => {
1883
+ const relatedGraphic = this._idToGraphic.get(text.attribute.id);
1807
1884
  const state = prevTextMap?.get(relatedGraphic) ? 'update' : 'enter';
1808
1885
  if (state === 'enter') {
1809
1886
  texts.push(text);
1810
1887
  currentTextMap.set(relatedGraphic, text);
1811
1888
  if (!disableAnimation && relatedGraphic) {
1812
- const { from, to } = getAnimationAttributes(label, 'fadeIn');
1889
+ const { from, to } = getAnimationAttributes(text.attribute, 'fadeIn');
1813
1890
  this.add(text);
1814
1891
  relatedGraphic.onAnimateBind = () => {
1815
1892
  text.setAttributes(from);
@@ -1859,7 +1936,7 @@
1859
1936
  });
1860
1937
  }
1861
1938
  });
1862
- this._textMap = currentTextMap;
1939
+ this._graphicToText = currentTextMap;
1863
1940
  }
1864
1941
  _afterRelatedGraphicAttributeUpdate(text, texts, index, relatedGraphic, { mode, duration, easing, to, delay }) {
1865
1942
  const listener = (event) => {
@@ -1910,30 +1987,34 @@
1910
1987
  return listener;
1911
1988
  }
1912
1989
  _smartInvert(labels) {
1913
- if (this.attribute.smartInvert === false) {
1914
- return;
1915
- }
1990
+ const option = (this.attribute.smartInvert || {});
1991
+ const { textType, contrastRatiosThreshold, alternativeColors } = option;
1916
1992
  for (let i = 0; i < labels.length; i++) {
1917
- const label = labels?.[i];
1993
+ const label = labels[i];
1918
1994
  if (!label) {
1919
1995
  continue;
1920
1996
  }
1921
- const isInside = canPlaceInside(vrender.createText(label).AABBBounds, this._relationMap.get(label._relatedIndex)?.AABBBounds);
1922
- if (label.stroke && label.lineWidth > 0) {
1923
- label.fill = labelSmartInvert(label.fill, label.stroke, this.attribute.smartInvert?.textType, this.attribute.smartInvert?.contrastRatiosThreshold, this.attribute.smartInvert?.alternativeColors);
1997
+ const baseMark = this._idToGraphic.get(label.attribute.id);
1998
+ const isInside = canPlaceInside(label.AABBBounds, baseMark?.AABBBounds);
1999
+ if (label.attribute.stroke && label.attribute.lineWidth > 0) {
2000
+ label.setAttributes({
2001
+ fill: labelSmartInvert(label.attribute.fill, label.attribute.stroke, textType, contrastRatiosThreshold, alternativeColors)
2002
+ });
1924
2003
  }
1925
2004
  else if (isInside) {
1926
- const baseMark = this._relationMap.get(label._relatedIndex);
1927
2005
  const backgroundColor = baseMark.attribute.fill;
1928
- const foregroundColor = label.fill;
1929
- label.fill = labelSmartInvert(foregroundColor, backgroundColor, this.attribute.smartInvert?.textType, this.attribute.smartInvert?.contrastRatiosThreshold, this.attribute.smartInvert?.alternativeColors);
2006
+ const foregroundColor = label.attribute.fill;
2007
+ label.setAttributes({
2008
+ fill: labelSmartInvert(foregroundColor, backgroundColor, textType, contrastRatiosThreshold, alternativeColors)
2009
+ });
1930
2010
  }
1931
- else if (label.lineWidth > 0) {
1932
- const baseMark = this._relationMap.get(label._relatedIndex);
1933
- label.stroke = baseMark.attribute.fill;
1934
- const backgroundColor = label.stroke;
1935
- const foregroundColor = label.fill;
1936
- label.fill = labelSmartInvert(foregroundColor, backgroundColor, this.attribute.smartInvert?.textType, this.attribute.smartInvert?.contrastRatiosThreshold, this.attribute.smartInvert?.alternativeColors);
2011
+ else if (label.attribute.lineWidth > 0) {
2012
+ const backgroundColor = label.attribute.stroke;
2013
+ const foregroundColor = label.attribute.fill;
2014
+ label.setAttributes({
2015
+ stroke: baseMark.attribute.fill,
2016
+ fill: labelSmartInvert(foregroundColor, backgroundColor, textType, contrastRatiosThreshold, alternativeColors)
2017
+ });
1937
2018
  }
1938
2019
  }
1939
2020
  }
@@ -2388,6 +2469,7 @@
2388
2469
  },
2389
2470
  startSymbol: {
2390
2471
  visible: false,
2472
+ autoRotate: true,
2391
2473
  symbolType: 'triangle',
2392
2474
  size: 12,
2393
2475
  refX: 0,
@@ -2400,6 +2482,7 @@
2400
2482
  },
2401
2483
  endSymbol: {
2402
2484
  visible: false,
2485
+ autoRotate: true,
2403
2486
  symbolType: 'triangle',
2404
2487
  size: 12,
2405
2488
  refX: 0,
@@ -2471,6 +2554,7 @@
2471
2554
  this.add(line);
2472
2555
  }
2473
2556
  renderSymbol(attribute, dim) {
2557
+ const { autoRotate = true } = attribute;
2474
2558
  let symbol;
2475
2559
  if (attribute?.visible) {
2476
2560
  const startAngle = this._startAngle;
@@ -2499,7 +2583,7 @@
2499
2583
  ...position,
2500
2584
  symbolType: symbolType,
2501
2585
  size,
2502
- angle: rotate + refAngle,
2586
+ angle: autoRotate ? rotate + refAngle : 0,
2503
2587
  strokeBoundsBuffer: 0,
2504
2588
  ...style
2505
2589
  });
@@ -9537,7 +9621,7 @@
9537
9621
  }
9538
9622
  }
9539
9623
 
9540
- const version = "0.13.7";
9624
+ const version = "0.13.8-alpha.4";
9541
9625
 
9542
9626
  exports.AbstractComponent = AbstractComponent;
9543
9627
  exports.BasePlayer = BasePlayer;