@visactor/vrender-components 0.13.5 → 0.13.6

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.
@@ -1,12 +1,10 @@
1
- import type { IBoundsLike } from '@visactor/vutils';
1
+ import { IBoundsLike } from '@visactor/vutils';
2
+ import type { ITextGraphicAttribute } from '@visactor/vrender';
2
3
  import type { SymbolLabelAttrs } from './type';
3
4
  import { LabelBase } from './base';
4
5
  export declare class SymbolLabel extends LabelBase<SymbolLabelAttrs> {
5
6
  name: string;
6
7
  static defaultAttributes: Partial<SymbolLabelAttrs>;
7
8
  constructor(attributes: SymbolLabelAttrs);
8
- protected labeling(textBounds: IBoundsLike, graphicBounds: IBoundsLike, position?: string, offset?: number): {
9
- x: number;
10
- y: number;
11
- };
9
+ protected labeling(textBounds: IBoundsLike, graphicBounds: IBoundsLike, position?: string, offset?: number): Partial<ITextGraphicAttribute> | undefined;
12
10
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["label/symbol.ts"],"names":[],"mappings":"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","file":"symbol.js","sourcesContent":["import type { IBoundsLike } from '@visactor/vutils';\nimport { merge } from '@visactor/vutils';\nimport type { ITextGraphicAttribute } from '@visactor/vrender';\nimport type { SymbolLabelAttrs } from './type';\nimport { LabelBase } from './base';\n\nexport class SymbolLabel extends LabelBase<SymbolLabelAttrs> {\n name = 'symbol-label';\n\n static defaultAttributes: Partial<SymbolLabelAttrs> = {\n textStyle: {\n fontSize: 12,\n fill: '#000',\n textAlign: 'center',\n textBaseline: 'middle',\n boundsPadding: [-1, 0, -1, 0] // to ignore the textBound buf\n },\n position: 'top',\n offset: 5,\n pickable: false\n };\n\n constructor(attributes: SymbolLabelAttrs) {\n super(merge({}, SymbolLabel.defaultAttributes, attributes));\n }\n\n protected labeling(textBounds: IBoundsLike, graphicBounds: IBoundsLike, position = 'top', offset = 0) {\n if (!textBounds) {\n return;\n }\n\n const { x1, y1, x2, y2 } = textBounds;\n const width = Math.abs(x2 - x1);\n const height = Math.abs(y2 - y1);\n\n const anchorX = (graphicBounds.x1 + graphicBounds.x2) / 2;\n const anchorY = (graphicBounds.y1 + graphicBounds.y2) / 2;\n\n let sx = 0;\n let sy = 0;\n let offsetX = 0;\n let offsetY = 0;\n if (graphicBounds) {\n offsetX = Math.abs(graphicBounds.x1 - graphicBounds.x2) / 2;\n offsetY = Math.abs(graphicBounds.y1 - graphicBounds.y2) / 2;\n }\n\n const angle = {\n 'top-right': -235,\n 'top-left': 235,\n 'bottom-right': 45,\n 'bottom-left': -45\n };\n\n switch (position) {\n case 'top':\n sy = -1;\n break;\n case 'bottom':\n sy = 1;\n break;\n case 'left':\n sx = -1;\n break;\n case 'right':\n sx = 1;\n break;\n case 'bottom-left':\n case 'bottom-right':\n case 'top-left':\n case 'top-right':\n sx = Math.sin(angle[position] * (Math.PI / 180));\n sy = Math.cos(angle[position] * (Math.PI / 180));\n break;\n case 'center':\n sx = 0;\n sy = 0;\n break;\n }\n\n const x = anchorX + sx * (offset + offsetX) + Math.sign(sx) * (width / 2);\n const y = anchorY + sy * (offset + offsetY) + Math.sign(sy) * (height / 2);\n\n return { x, y };\n }\n}\n"]}
1
+ {"version":3,"sources":["label/symbol.ts"],"names":[],"mappings":"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","file":"symbol.js","sourcesContent":["import { merge, IBoundsLike } from '@visactor/vutils';\nimport type { ITextGraphicAttribute } from '@visactor/vrender';\nimport type { SymbolLabelAttrs } from './type';\nimport { LabelBase } from './base';\n\nexport class SymbolLabel extends LabelBase<SymbolLabelAttrs> {\n name = 'symbol-label';\n\n static defaultAttributes: Partial<SymbolLabelAttrs> = {\n textStyle: {\n fontSize: 12,\n fill: '#000',\n textAlign: 'center',\n textBaseline: 'middle',\n boundsPadding: [-1, 0, -1, 0] // to ignore the textBound buf\n },\n position: 'top',\n offset: 5,\n pickable: false\n };\n\n constructor(attributes: SymbolLabelAttrs) {\n super(merge({}, SymbolLabel.defaultAttributes, attributes));\n }\n\n protected labeling(\n textBounds: IBoundsLike,\n graphicBounds: IBoundsLike,\n position = 'top',\n offset = 0\n ): Partial<ITextGraphicAttribute> | undefined {\n if (!textBounds) {\n return;\n }\n\n const { x1, y1, x2, y2 } = textBounds;\n const width = Math.abs(x2 - x1);\n const height = Math.abs(y2 - y1);\n\n const anchorX = (graphicBounds.x1 + graphicBounds.x2) / 2;\n const anchorY = (graphicBounds.y1 + graphicBounds.y2) / 2;\n\n let sx = 0;\n let sy = 0;\n let offsetX = 0;\n let offsetY = 0;\n if (graphicBounds) {\n offsetX = Math.abs(graphicBounds.x1 - graphicBounds.x2) / 2;\n offsetY = Math.abs(graphicBounds.y1 - graphicBounds.y2) / 2;\n }\n\n const angle = {\n 'top-right': -235,\n 'top-left': 235,\n 'bottom-right': 45,\n 'bottom-left': -45\n };\n\n switch (position) {\n case 'top':\n sy = -1;\n break;\n case 'bottom':\n sy = 1;\n break;\n case 'left':\n sx = -1;\n break;\n case 'right':\n sx = 1;\n break;\n case 'bottom-left':\n case 'bottom-right':\n case 'top-left':\n case 'top-right':\n sx = Math.sin(angle[position] * (Math.PI / 180));\n sy = Math.cos(angle[position] * (Math.PI / 180));\n break;\n case 'center':\n sx = 0;\n sy = 0;\n break;\n }\n\n const x = anchorX + sx * (offset + offsetX) + Math.sign(sx) * (width / 2);\n const y = anchorY + sy * (offset + offsetY) + Math.sign(sy) * (height / 2);\n\n return { x, y };\n }\n}\n"]}
@@ -1,21 +1,17 @@
1
- import type { EasingType, IGraphic, IGroupGraphicAttribute, ITextGraphicAttribute, Text } from '@visactor/vrender';
1
+ import type { EasingType, IGroupGraphicAttribute, ITextGraphicAttribute } from '@visactor/vrender';
2
2
  export type LabelItemStateStyle<T> = {
3
3
  hover?: T;
4
4
  hover_reverse?: T;
5
5
  selected?: T;
6
6
  selected_reverse?: T;
7
7
  };
8
- export type LabelItem = {
9
- id?: string;
10
- data?: any;
11
- [key: string]: any;
12
- } & ITextGraphicAttribute;
13
8
  export interface BaseLabelAttrs extends IGroupGraphicAttribute {
14
9
  type: string;
15
- baseMarkGroupName: string;
16
10
  select?: boolean;
17
11
  hover?: boolean;
18
- data: LabelItem[];
12
+ data: Functional<(ITextGraphicAttribute & Record<string, any>)[]>;
13
+ sort?: (graphicA: any, graphicB: any) => number;
14
+ baseMarkGroupName?: string;
19
15
  textStyle?: Partial<ITextGraphicAttribute>;
20
16
  state?: LabelItemStateStyle<ITextGraphicAttribute>;
21
17
  position?: Functional<string>;
@@ -23,9 +19,6 @@ export interface BaseLabelAttrs extends IGroupGraphicAttribute {
23
19
  overlap?: OverlapAttrs | false;
24
20
  smartInvert?: SmartInvertAttrs | false;
25
21
  animation?: ILabelAnimation | false;
26
- dataFilter?: (data: LabelItem[]) => LabelItem[];
27
- customLayoutFunc?: (data: LabelItem[], getRelatedGraphic: (data: LabelItem) => IGraphic) => Text[];
28
- customOverlapFunc?: (label: Text[], getRelatedGraphic: (data: LabelItem) => IGraphic) => Text[];
29
22
  }
30
23
  export interface OverlapAttrs {
31
24
  size?: {
@@ -82,6 +75,9 @@ export interface DataLabelAttrs extends IGroupGraphicAttribute {
82
75
  };
83
76
  }
84
77
  export type Functional<T> = T | ((data: any) => T);
78
+ export interface ILabelGraphicAttribute extends ITextGraphicAttribute {
79
+ _relatedIndex?: number;
80
+ }
85
81
  export interface ILabelAnimation {
86
82
  mode?: 'same-time' | 'after' | 'after-all';
87
83
  duration?: number;
@@ -1 +1 @@
1
- {"version":3,"sources":["label/type.ts"],"names":[],"mappings":"","file":"type.js","sourcesContent":["import type { EasingType, IGraphic, IGroupGraphicAttribute, ITextGraphicAttribute, Text } from '@visactor/vrender';\n\nexport type LabelItemStateStyle<T> = {\n hover?: T;\n hover_reverse?: T;\n selected?: T;\n selected_reverse?: T;\n};\n\nexport type LabelItem = {\n // 用于动画\n id?: string;\n // 原始数据\n data?: any;\n [key: string]: any;\n} & ITextGraphicAttribute;\n\nexport interface BaseLabelAttrs extends IGroupGraphicAttribute {\n type: string;\n /**\n * 图元 group 名称\n */\n baseMarkGroupName: string;\n /**\n * 是否开启选中交互\n * @default false\n */\n select?: boolean;\n /**\n * 是否开启 hover 交互\n * @default false\n */\n hover?: boolean;\n /**\n * 标签数据\n */\n data: LabelItem[];\n\n /** 文本样式,优先级低于 data */\n textStyle?: Partial<ITextGraphicAttribute>;\n\n /** 文本交互样式 */\n state?: LabelItemStateStyle<ITextGraphicAttribute>;\n\n /** 标签默认位置 */\n position?: Functional<string>;\n\n /** 偏移量 */\n offset?: number;\n\n /** 是否开启防重叠\n * @default true\n */\n overlap?: OverlapAttrs | false;\n\n /** 智能反色 */\n smartInvert?: SmartInvertAttrs | false;\n\n /** 动画配置 */\n animation?: ILabelAnimation | false;\n\n // 排序 or 删减\n dataFilter?: (data: LabelItem[]) => LabelItem[];\n\n /** 自定义布局函数\n * @description 当配置了 customLayoutFunc 后,默认布局和防重叠逻辑将不再生效。(overlap/position/offset不生效)\n */\n customLayoutFunc?: (data: LabelItem[], getRelatedGraphic: (data: LabelItem) => IGraphic) => Text[];\n\n /** 自定义标签躲避函数\n * @description 当配置了 customOverlapFunc 后,会根据 position 和 offset 进行初始布局。配置的防重叠逻辑(overlap)不生效。\n */\n customOverlapFunc?: (label: Text[], getRelatedGraphic: (data: LabelItem) => IGraphic) => Text[];\n}\n\nexport interface OverlapAttrs {\n /**\n * 防重叠的区域大小\n */\n size?: { width: number; height: number };\n\n /**\n * 发生重叠后,是否隐藏标签\n * @default true\n */\n hideOnHit?: boolean;\n\n /**\n * 是否约束标签在指定 size 的范围内。开启后若标签被区域裁剪,会向内收缩。\n * @default true\n */\n clampForce?: boolean;\n\n /**\n * 是否躲避基础图元\n * @default false\n */\n avoidBaseMark?: boolean;\n\n /**\n * 发生重叠后的躲避策略\n */\n strategy?: Strategy[];\n}\n\nexport interface SmartInvertAttrs {\n /**\n * 文本类型\n * 包含普通文本和大文本,对应不同的对比度标准,label默认为普通文本\n * 'normalText' | 'largeText'\n * @default 'normalText'\n */\n textType?: string;\n /**\n * 自定义对比度阈值\n */\n contrastRatiosThreshold?: number;\n /**\n * 自定义备选label颜色\n */\n alternativeColors?: string | string[];\n}\n\nexport type PositionStrategy = {\n /**\n * 可选位置策略。\n * 若默认位置没有足够的空间放置标签,则考虑 position 内的备选位置。\n */\n type: 'position';\n position?: Functional<LabelPosition[]>;\n};\n\nexport type BoundStrategy = {\n /**\n * 标签配置在图形内部时使用。\n * 当图形大小不足以放下标签,则考虑 position 内的备选位置。\n */\n type: 'bound';\n position?: Functional<LabelPosition[]>;\n};\n\nexport type MoveYStrategy = {\n /**\n * 可选位置策略。\n * 若默认位置没有足够的空间放置标签,则根据 offset 在Y方向上寻找位置。\n */\n type: 'moveY';\n /**\n * Y方向上的尝试的位置偏移量\n */\n offset: Functional<number[]>;\n};\n\nexport type MoveXStrategy = {\n /**\n * 可选位置策略。\n * 若默认位置没有足够的空间放置标签,则根据 offset 在X方向上寻找位置。\n */\n type: 'moveX';\n /**\n * X方向上的尝试的位置偏移量\n */\n offset: Functional<number[]>;\n};\n\nexport type Strategy = PositionStrategy | BoundStrategy | MoveYStrategy | MoveXStrategy;\n\nexport type LabelPosition = SymbolLabelAttrs['position'] | RectLabelAttrs['position'];\n\nexport interface SymbolLabelAttrs extends BaseLabelAttrs {\n type: 'symbol';\n\n /**\n * 标签位置\n * @default 'top'\n */\n position?: Functional<\n 'top' | 'bottom' | 'left' | 'right' | 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'center'\n >;\n}\n\nexport interface RectLabelAttrs extends BaseLabelAttrs {\n type: 'rect';\n\n /**\n * 图元 group 名称\n */\n baseMarkGroupName: string;\n\n /**\n * 标签位置\n * @default 'top'\n */\n position?: Functional<\n 'top' | 'bottom' | 'left' | 'right' | 'inside' | 'inside-top' | 'inside-bottom' | 'inside-right' | 'inside-left'\n >;\n}\n\nexport interface LineLabelAttrs extends BaseLabelAttrs {\n type: 'line';\n\n /**\n * 图元 group 名称\n */\n baseMarkGroupName: string;\n\n /**\n * 标签位置\n * @default 'end'\n */\n position?: Functional<'start' | 'end'>;\n}\n\nexport interface DataLabelAttrs extends IGroupGraphicAttribute {\n dataLabels: (RectLabelAttrs | SymbolLabelAttrs)[];\n /**\n * 防重叠的区域大小\n */\n size: { width: number; height: number };\n}\n\nexport type Functional<T> = T | ((data: any) => T);\n\nexport interface ILabelAnimation {\n mode?: 'same-time' | 'after' | 'after-all';\n duration?: number;\n delay?: number;\n easing?: EasingType;\n /** 是否开启 increaseCount 动画\n * @default true\n */\n increaseEffect?: boolean;\n}\n"]}
1
+ {"version":3,"sources":["label/type.ts"],"names":[],"mappings":"","file":"type.js","sourcesContent":["import type { EasingType, IGroupGraphicAttribute, ITextGraphicAttribute } from '@visactor/vrender';\nimport type { Bounds } from '@visactor/vutils';\n\nexport type LabelItemStateStyle<T> = {\n hover?: T;\n hover_reverse?: T;\n selected?: T;\n selected_reverse?: T;\n};\n\nexport interface BaseLabelAttrs extends IGroupGraphicAttribute {\n type: string;\n /**\n * 是否开启选中交互\n * @default false\n */\n select?: boolean;\n /**\n * 是否开启 hover 交互\n * @default false\n */\n hover?: boolean;\n /**\n * 标签数据\n */\n data: Functional<(ITextGraphicAttribute & Record<string, any>)[]>;\n\n sort?: (graphicA: any, graphicB: any) => number;\n\n /**\n * 图元 group 名称\n * 如果不配置,需要在 data 里指定标签定位 x/y\n */\n baseMarkGroupName?: string;\n\n /** 文本样式,优先级低于 data */\n textStyle?: Partial<ITextGraphicAttribute>;\n\n /** 文本交互样式 */\n state?: LabelItemStateStyle<ITextGraphicAttribute>;\n\n /** 标签默认位置 */\n position?: Functional<string>;\n\n /** 偏移量 */\n offset?: number;\n\n /** 是否开启防重叠\n * @default true\n */\n overlap?: OverlapAttrs | false;\n\n /** 智能反色 */\n smartInvert?: SmartInvertAttrs | false;\n\n /** 动画配置 */\n animation?: ILabelAnimation | false;\n}\n\nexport interface OverlapAttrs {\n /**\n * 防重叠的区域大小\n */\n size?: { width: number; height: number };\n\n /**\n * 发生重叠后,是否隐藏标签\n * @default true\n */\n hideOnHit?: boolean;\n\n /**\n * 是否约束标签在指定 size 的范围内。开启后若标签被区域裁剪,会向内收缩。\n * @default true\n */\n clampForce?: boolean;\n\n /**\n * 是否躲避基础图元\n * @default false\n */\n avoidBaseMark?: boolean;\n\n /**\n * 发生重叠后的躲避策略\n */\n strategy?: Strategy[];\n}\n\nexport interface SmartInvertAttrs {\n /**\n * 文本类型\n * 包含普通文本和大文本,对应不同的对比度标准,label默认为普通文本\n * 'normalText' | 'largeText'\n * @default 'normalText'\n */\n textType?: string;\n /**\n * 自定义对比度阈值\n */\n contrastRatiosThreshold?: number;\n /**\n * 自定义备选label颜色\n */\n alternativeColors?: string | string[];\n}\n\nexport type PositionStrategy = {\n /**\n * 可选位置策略。\n * 若默认位置没有足够的空间放置标签,则考虑 position 内的备选位置。\n */\n type: 'position';\n position?: Functional<LabelPosition[]>;\n};\n\nexport type BoundStrategy = {\n /**\n * 标签配置在图形内部时使用。\n * 当图形大小不足以放下标签,则考虑 position 内的备选位置。\n */\n type: 'bound';\n position?: Functional<LabelPosition[]>;\n};\n\nexport type MoveYStrategy = {\n /**\n * 可选位置策略。\n * 若默认位置没有足够的空间放置标签,则根据 offset 在Y方向上寻找位置。\n */\n type: 'moveY';\n /**\n * Y方向上的尝试的位置偏移量\n */\n offset: Functional<number[]>;\n};\n\nexport type MoveXStrategy = {\n /**\n * 可选位置策略。\n * 若默认位置没有足够的空间放置标签,则根据 offset 在X方向上寻找位置。\n */\n type: 'moveX';\n /**\n * X方向上的尝试的位置偏移量\n */\n offset: Functional<number[]>;\n};\n\nexport type Strategy = PositionStrategy | BoundStrategy | MoveYStrategy | MoveXStrategy;\n\nexport type LabelPosition = SymbolLabelAttrs['position'] | RectLabelAttrs['position'];\n\nexport interface SymbolLabelAttrs extends BaseLabelAttrs {\n type: 'symbol';\n\n /**\n * 标签位置\n * @default 'top'\n */\n position?: Functional<\n 'top' | 'bottom' | 'left' | 'right' | 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'center'\n >;\n}\n\nexport interface RectLabelAttrs extends BaseLabelAttrs {\n type: 'rect';\n\n /**\n * 图元 group 名称\n */\n baseMarkGroupName: string;\n\n /**\n * 标签位置\n * @default 'top'\n */\n position?: Functional<\n 'top' | 'bottom' | 'left' | 'right' | 'inside' | 'inside-top' | 'inside-bottom' | 'inside-right' | 'inside-left'\n >;\n}\n\nexport interface LineLabelAttrs extends BaseLabelAttrs {\n type: 'line';\n\n /**\n * 图元 group 名称\n */\n baseMarkGroupName: string;\n\n /**\n * 标签位置\n * @default 'end'\n */\n position?: Functional<'start' | 'end'>;\n}\n\nexport interface DataLabelAttrs extends IGroupGraphicAttribute {\n dataLabels: (RectLabelAttrs | SymbolLabelAttrs)[];\n /**\n * 防重叠的区域大小\n */\n size: { width: number; height: number };\n}\n\nexport type Functional<T> = T | ((data: any) => T);\n\nexport interface ILabelGraphicAttribute extends ITextGraphicAttribute {\n _relatedIndex?: number;\n}\n\nexport interface ILabelAnimation {\n mode?: 'same-time' | 'after' | 'after-all';\n duration?: number;\n delay?: number;\n easing?: EasingType;\n /** 是否开启 increaseCount 动画\n * @default true\n */\n increaseEffect?: boolean;\n}\n"]}
package/dist/index.js CHANGED
@@ -1514,28 +1514,6 @@
1514
1514
  return DefaultPositions;
1515
1515
  }
1516
1516
  }
1517
- function clampText(text, width, height) {
1518
- const { x1, x2, y1, y2 } = text.AABBBounds;
1519
- const minX = Math.min(x1, x2);
1520
- const maxX = Math.max(x1, x2);
1521
- const minY = Math.min(y1, y2);
1522
- const maxY = Math.max(y1, y2);
1523
- let dx = 0;
1524
- let dy = 0;
1525
- if (minX < 0 && maxX - minX <= width) {
1526
- dx = -minX;
1527
- }
1528
- else if (maxX > width && minX - (maxX - width) >= 0) {
1529
- dx = width - maxX;
1530
- }
1531
- if (minY < 0 && maxY - minY <= height) {
1532
- dy = -minY;
1533
- }
1534
- else if (maxY > height && minY - (maxY - height) >= 0) {
1535
- dy = height - maxY;
1536
- }
1537
- return { dx, dy };
1538
- }
1539
1517
 
1540
1518
  const fadeIn = (textAttribute = {}) => {
1541
1519
  return {
@@ -1586,37 +1564,17 @@
1586
1564
  setBitmapTool(bmpTool) {
1587
1565
  this._bmpTool = bmpTool;
1588
1566
  }
1589
- _graphicToText;
1590
- _idToGraphic;
1567
+ _relationMap;
1568
+ _prevRelationMap;
1569
+ _textMap;
1591
1570
  onAfterLabelOverlap;
1592
1571
  _lastHover;
1593
1572
  _lastSelect;
1594
1573
  _enableAnimation;
1595
1574
  render() {
1596
- this._prepare();
1597
- const { overlap, smartInvert, dataFilter, customLayoutFunc, customOverlapFunc } = this.attribute;
1598
- let data = this.attribute.data;
1599
- if (vutils.isFunction(dataFilter)) {
1600
- data = dataFilter(data);
1601
- }
1602
- let labels;
1603
- if (vutils.isFunction(customLayoutFunc)) {
1604
- labels = customLayoutFunc(data, (d) => this._idToGraphic.get(d.id));
1605
- }
1606
- else {
1607
- labels = this.layout(data);
1608
- if (vutils.isFunction(customOverlapFunc)) {
1609
- labels = customOverlapFunc(labels, (d) => this._idToGraphic.get(d.id));
1610
- }
1611
- else {
1612
- if (overlap !== false) {
1613
- labels = this._overlapping(labels);
1614
- }
1615
- }
1616
- }
1617
- if (smartInvert !== false) {
1618
- this._smartInvert(labels);
1619
- }
1575
+ const currentBaseMarks = this._checkMarks();
1576
+ const labels = this.layout(currentBaseMarks);
1577
+ this._smartInvert(labels);
1620
1578
  this._renderLabels(labels);
1621
1579
  }
1622
1580
  _bindEvent(target) {
@@ -1693,7 +1651,7 @@
1693
1651
  this._setStates(text);
1694
1652
  return text;
1695
1653
  }
1696
- _prepare() {
1654
+ _checkMarks() {
1697
1655
  const baseMarks = this.getBaseMarks();
1698
1656
  const currentBaseMarks = [];
1699
1657
  baseMarks.forEach(mark => {
@@ -1701,58 +1659,59 @@
1701
1659
  currentBaseMarks.push(mark);
1702
1660
  }
1703
1661
  });
1704
- this._idToGraphic?.clear();
1705
- this._baseMarks = currentBaseMarks;
1706
- if (!currentBaseMarks || currentBaseMarks.length === 0) {
1707
- return;
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({});
1708
1671
  }
1709
- const { data } = this.attribute;
1710
1672
  if (!data || data.length === 0) {
1711
- return;
1673
+ return [];
1712
1674
  }
1713
- if (!this._idToGraphic) {
1714
- this._idToGraphic = new Map();
1675
+ let labels = [];
1676
+ if (vutils.isFunction(this.attribute.sort) && currentMarks && currentMarks.length) {
1677
+ currentMarks = currentMarks.sort(this.attribute.sort);
1715
1678
  }
1716
- for (let i = 0; i < currentBaseMarks.length; i++) {
1717
- const textData = data[i];
1718
- const baseMark = currentBaseMarks[i];
1719
- if (textData && baseMark) {
1720
- if (!vutils.isValid(textData.id)) {
1721
- textData.id = `vrender-component-${this.name}-${i}`;
1722
- }
1723
- this._idToGraphic.set(textData.id, baseMark);
1724
- }
1679
+ if (!this._relationMap) {
1680
+ this._relationMap = new Map();
1725
1681
  }
1726
- }
1727
- layout(data = []) {
1728
- const { textStyle = {}, position, offset } = this.attribute;
1729
- const labels = [];
1730
1682
  for (let i = 0; i < data.length; i++) {
1731
1683
  const textData = data[i];
1732
- const baseMark = this._idToGraphic.get(textData.id);
1684
+ const baseMark = currentMarks?.[i];
1733
1685
  const labelAttribute = {
1734
1686
  ...textStyle,
1735
- ...textData
1687
+ ...textData,
1688
+ _relatedIndex: i
1736
1689
  };
1737
- const text = this._createLabelText(labelAttribute);
1738
- const textBounds = this.getGraphicBounds(text);
1739
- const graphicBounds = this.getGraphicBounds(baseMark, { x: textData.x, y: textData.y });
1740
- const textLocation = this.labeling(textBounds, graphicBounds, vutils.isFunction(position) ? position(textData) : position, offset);
1741
- if (!textLocation) {
1742
- continue;
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);
1743
1703
  }
1744
- labelAttribute.x = textLocation.x;
1745
- labelAttribute.y = textLocation.y;
1746
- text.setAttributes(textLocation);
1747
- labels.push(text);
1704
+ }
1705
+ this._baseMarks = currentMarks;
1706
+ if (this.attribute.overlap !== false) {
1707
+ labels = this.overlapping(labels, this.attribute.overlap);
1748
1708
  }
1749
1709
  return labels;
1750
1710
  }
1751
- _overlapping(labels) {
1711
+ overlapping(labels, option = {}) {
1752
1712
  if (labels.length === 0) {
1753
1713
  return [];
1754
1714
  }
1755
- const option = this.attribute.overlap;
1756
1715
  const result = [];
1757
1716
  const baseMarkGroup = this.getBaseMarkGroup();
1758
1717
  const size = option.size ?? {
@@ -1775,32 +1734,18 @@
1775
1734
  if (labels[i].visible === false) {
1776
1735
  continue;
1777
1736
  }
1778
- const text = labels[i];
1779
- const baseMark = this._idToGraphic.get(text.attribute.id);
1737
+ const text = vrender.createText(labels[i]);
1738
+ const baseMark = this._baseMarks?.[i];
1780
1739
  text.update();
1781
1740
  if (canPlace(bmpTool, bitmap, text.AABBBounds, clampForce)) {
1782
1741
  if (!checkBounds) {
1783
1742
  bitmap.setRange(boundToRange(bmpTool, text.AABBBounds, true));
1784
- result.push(text);
1743
+ result.push({ ...text.attribute });
1785
1744
  continue;
1786
1745
  }
1787
1746
  if (checkBounds && baseMark?.AABBBounds && canPlaceInside(text.AABBBounds, baseMark?.AABBBounds)) {
1788
1747
  bitmap.setRange(boundToRange(bmpTool, text.AABBBounds, true));
1789
- result.push(text);
1790
- continue;
1791
- }
1792
- }
1793
- if (clampForce) {
1794
- const { dx = 0, dy = 0 } = clampText(text, bmpTool.width, bmpTool.height);
1795
- if (!(dx === 0 && dy === 0) &&
1796
- canPlace(bmpTool, bitmap, {
1797
- x1: text.AABBBounds.x1 + dx,
1798
- x2: text.AABBBounds.x2 + dx,
1799
- y1: text.AABBBounds.y1 + dy,
1800
- y2: text.AABBBounds.y2 + dy
1801
- })) {
1802
- text.setAttributes({ x: text.attribute.x + dx, y: text.attribute.y + dy });
1803
- result.push(text);
1748
+ result.push({ ...text.attribute });
1804
1749
  continue;
1805
1750
  }
1806
1751
  }
@@ -1808,12 +1753,15 @@
1808
1753
  for (let j = 0; j < strategy.length; j++) {
1809
1754
  hasPlace = place(bmpTool, bitmap, strategy[j], this.attribute, text, this.getGraphicBounds(baseMark, labels[i]), this.labeling);
1810
1755
  if (hasPlace !== false) {
1811
- text.setAttributes({ x: hasPlace.x, y: hasPlace.y });
1812
- result.push(text);
1756
+ result.push({
1757
+ ...text.attribute,
1758
+ x: hasPlace.x,
1759
+ y: hasPlace.y
1760
+ });
1813
1761
  break;
1814
1762
  }
1815
1763
  }
1816
- !hasPlace && !hideOnHit && result.push(text);
1764
+ !hasPlace && !hideOnHit && result.push({ ...text.attribute });
1817
1765
  }
1818
1766
  if (vutils.isFunction(this.onAfterLabelOverlap)) {
1819
1767
  this.onAfterLabelOverlap(bitmap);
@@ -1851,16 +1799,17 @@
1851
1799
  const easing = animationConfig.easing ?? DefaultLabelAnimation.easing;
1852
1800
  const delay = animationConfig.delay ?? 0;
1853
1801
  const currentTextMap = new Map();
1854
- const prevTextMap = this._graphicToText || new Map();
1802
+ const prevTextMap = this._textMap || new Map();
1855
1803
  const texts = [];
1856
- labels.forEach((text, index) => {
1857
- const relatedGraphic = this._idToGraphic.get(text.attribute.id);
1804
+ labels.forEach((label, index) => {
1805
+ const text = this._createLabelText(label);
1806
+ const relatedGraphic = this._relationMap.get(label._relatedIndex);
1858
1807
  const state = prevTextMap?.get(relatedGraphic) ? 'update' : 'enter';
1859
1808
  if (state === 'enter') {
1860
1809
  texts.push(text);
1861
1810
  currentTextMap.set(relatedGraphic, text);
1862
1811
  if (!disableAnimation && relatedGraphic) {
1863
- const { from, to } = getAnimationAttributes(text.attribute, 'fadeIn');
1812
+ const { from, to } = getAnimationAttributes(label, 'fadeIn');
1864
1813
  this.add(text);
1865
1814
  relatedGraphic.onAnimateBind = () => {
1866
1815
  text.setAttributes(from);
@@ -1910,7 +1859,7 @@
1910
1859
  });
1911
1860
  }
1912
1861
  });
1913
- this._graphicToText = currentTextMap;
1862
+ this._textMap = currentTextMap;
1914
1863
  }
1915
1864
  _afterRelatedGraphicAttributeUpdate(text, texts, index, relatedGraphic, { mode, duration, easing, to, delay }) {
1916
1865
  const listener = (event) => {
@@ -1961,34 +1910,30 @@
1961
1910
  return listener;
1962
1911
  }
1963
1912
  _smartInvert(labels) {
1964
- const option = (this.attribute.smartInvert || {});
1965
- const { textType, contrastRatiosThreshold, alternativeColors } = option;
1913
+ if (this.attribute.smartInvert === false) {
1914
+ return;
1915
+ }
1966
1916
  for (let i = 0; i < labels.length; i++) {
1967
- const label = labels[i];
1917
+ const label = labels?.[i];
1968
1918
  if (!label) {
1969
1919
  continue;
1970
1920
  }
1971
- const baseMark = this._idToGraphic.get(label.attribute.id);
1972
- const isInside = canPlaceInside(label.AABBBounds, baseMark?.AABBBounds);
1973
- if (label.attribute.stroke && label.attribute.lineWidth > 0) {
1974
- label.setAttributes({
1975
- fill: labelSmartInvert(label.attribute.fill, label.attribute.stroke, textType, contrastRatiosThreshold, alternativeColors)
1976
- });
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);
1977
1924
  }
1978
1925
  else if (isInside) {
1926
+ const baseMark = this._relationMap.get(label._relatedIndex);
1979
1927
  const backgroundColor = baseMark.attribute.fill;
1980
- const foregroundColor = label.attribute.fill;
1981
- label.setAttributes({
1982
- fill: labelSmartInvert(foregroundColor, backgroundColor, textType, contrastRatiosThreshold, alternativeColors)
1983
- });
1928
+ const foregroundColor = label.fill;
1929
+ label.fill = labelSmartInvert(foregroundColor, backgroundColor, this.attribute.smartInvert?.textType, this.attribute.smartInvert?.contrastRatiosThreshold, this.attribute.smartInvert?.alternativeColors);
1984
1930
  }
1985
- else if (label.attribute.lineWidth > 0) {
1986
- const backgroundColor = label.attribute.stroke;
1987
- const foregroundColor = label.attribute.fill;
1988
- label.setAttributes({
1989
- stroke: baseMark.attribute.fill,
1990
- fill: labelSmartInvert(foregroundColor, backgroundColor, textType, contrastRatiosThreshold, alternativeColors)
1991
- });
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);
1992
1937
  }
1993
1938
  }
1994
1939
  }
@@ -9588,7 +9533,7 @@
9588
9533
  }
9589
9534
  }
9590
9535
 
9591
- const version = "0.13.5";
9536
+ const version = "0.13.6";
9592
9537
 
9593
9538
  exports.AbstractComponent = AbstractComponent;
9594
9539
  exports.BasePlayer = BasePlayer;