@visactor/vrender-components 0.21.0-vstory.1 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/cjs/axis/type.d.ts +2 -2
  2. package/cjs/axis/type.js.map +1 -1
  3. package/cjs/data-zoom/type.d.ts +1 -1
  4. package/cjs/data-zoom/type.js.map +1 -1
  5. package/cjs/index.d.ts +1 -2
  6. package/cjs/index.js +2 -2
  7. package/cjs/index.js.map +1 -1
  8. package/cjs/interface.d.ts +1 -2
  9. package/cjs/interface.js.map +1 -1
  10. package/cjs/label/arc.js +1 -1
  11. package/cjs/label/arc.js.map +1 -1
  12. package/cjs/label/base.js +20 -10
  13. package/cjs/label/base.js.map +1 -1
  14. package/cjs/label/overlap/place.d.ts +6 -1
  15. package/cjs/label/overlap/place.js +4 -4
  16. package/cjs/label/overlap/place.js.map +1 -1
  17. package/cjs/label/overlap/shiftY.d.ts +10 -4
  18. package/cjs/label/overlap/shiftY.js +103 -27
  19. package/cjs/label/overlap/shiftY.js.map +1 -1
  20. package/cjs/legend/color/type.d.ts +2 -2
  21. package/cjs/legend/color/type.js.map +1 -1
  22. package/cjs/legend/discrete/discrete.d.ts +7 -0
  23. package/cjs/legend/discrete/discrete.js +106 -23
  24. package/cjs/legend/discrete/discrete.js.map +1 -1
  25. package/cjs/legend/discrete/type.d.ts +16 -4
  26. package/cjs/legend/discrete/type.js.map +1 -1
  27. package/cjs/marker/type.d.ts +2 -2
  28. package/cjs/marker/type.js.map +1 -1
  29. package/cjs/player/type/discrete-player.d.ts +3 -3
  30. package/cjs/player/type/discrete-player.js.map +1 -1
  31. package/cjs/player/type/index.d.ts +2 -2
  32. package/cjs/player/type/index.js.map +1 -1
  33. package/cjs/radio/radio.d.ts +2 -2
  34. package/cjs/radio/radio.js +1 -1
  35. package/cjs/radio/radio.js.map +1 -1
  36. package/cjs/scrollbar/index.d.ts +1 -0
  37. package/cjs/scrollbar/index.js +2 -1
  38. package/cjs/scrollbar/index.js.map +1 -1
  39. package/cjs/scrollbar/scrollbar-plugin.d.ts +18 -15
  40. package/cjs/scrollbar/scrollbar-plugin.js +109 -97
  41. package/cjs/scrollbar/scrollbar-plugin.js.map +1 -1
  42. package/cjs/timeline/type.js.map +1 -1
  43. package/dist/index.es.js +9537 -9390
  44. package/es/axis/type.d.ts +2 -2
  45. package/es/axis/type.js.map +1 -1
  46. package/es/data-zoom/type.d.ts +1 -1
  47. package/es/data-zoom/type.js.map +1 -1
  48. package/es/index.d.ts +1 -2
  49. package/es/index.js +1 -3
  50. package/es/index.js.map +1 -1
  51. package/es/interface.d.ts +1 -2
  52. package/es/interface.js.map +1 -1
  53. package/es/label/arc.js +1 -1
  54. package/es/label/arc.js.map +1 -1
  55. package/es/label/base.js +20 -9
  56. package/es/label/base.js.map +1 -1
  57. package/es/label/overlap/place.d.ts +6 -1
  58. package/es/label/overlap/place.js +4 -4
  59. package/es/label/overlap/place.js.map +1 -1
  60. package/es/label/overlap/shiftY.d.ts +10 -4
  61. package/es/label/overlap/shiftY.js +99 -24
  62. package/es/label/overlap/shiftY.js.map +1 -1
  63. package/es/legend/color/type.d.ts +2 -2
  64. package/es/legend/color/type.js.map +1 -1
  65. package/es/legend/discrete/discrete.d.ts +7 -0
  66. package/es/legend/discrete/discrete.js +106 -24
  67. package/es/legend/discrete/discrete.js.map +1 -1
  68. package/es/legend/discrete/type.d.ts +16 -4
  69. package/es/legend/discrete/type.js.map +1 -1
  70. package/es/marker/type.d.ts +2 -2
  71. package/es/marker/type.js.map +1 -1
  72. package/es/player/type/discrete-player.d.ts +3 -3
  73. package/es/player/type/discrete-player.js.map +1 -1
  74. package/es/player/type/index.d.ts +2 -2
  75. package/es/player/type/index.js.map +1 -1
  76. package/es/radio/radio.d.ts +2 -2
  77. package/es/radio/radio.js +2 -2
  78. package/es/radio/radio.js.map +1 -1
  79. package/es/scrollbar/index.d.ts +1 -0
  80. package/es/scrollbar/index.js +2 -0
  81. package/es/scrollbar/index.js.map +1 -1
  82. package/es/scrollbar/scrollbar-plugin.d.ts +18 -15
  83. package/es/scrollbar/scrollbar-plugin.js +111 -94
  84. package/es/scrollbar/scrollbar-plugin.js.map +1 -1
  85. package/es/timeline/type.js.map +1 -1
  86. package/package.json +10 -9
  87. package/cjs/weather/index.d.ts +0 -1
  88. package/cjs/weather/index.js +0 -21
  89. package/cjs/weather/index.js.map +0 -1
  90. package/cjs/weather/register.d.ts +0 -1
  91. package/cjs/weather/register.js +0 -14
  92. package/cjs/weather/register.js.map +0 -1
  93. package/cjs/weather/type.d.ts +0 -24
  94. package/cjs/weather/type.js +0 -6
  95. package/cjs/weather/type.js.map +0 -1
  96. package/cjs/weather/weather-box.d.ts +0 -13
  97. package/cjs/weather/weather-box.js +0 -129
  98. package/cjs/weather/weather-box.js.map +0 -1
  99. package/es/weather/index.d.ts +0 -1
  100. package/es/weather/index.js +0 -2
  101. package/es/weather/index.js.map +0 -1
  102. package/es/weather/register.d.ts +0 -1
  103. package/es/weather/register.js +0 -6
  104. package/es/weather/register.js.map +0 -1
  105. package/es/weather/type.d.ts +0 -24
  106. package/es/weather/type.js +0 -2
  107. package/es/weather/type.js.map +0 -1
  108. package/es/weather/weather-box.d.ts +0 -13
  109. package/es/weather/weather-box.js +0 -127
  110. package/es/weather/weather-box.js.map +0 -1
@@ -1,41 +1,116 @@
1
- export function shiftY(texts, option = {}) {
2
- const {maxIterations: maxIterations = 10, maxError: maxError = .1, padding: padding = 1, maxY: maxY = Number.MAX_VALUE} = option, n = texts.length;
1
+ import { isNumberClose } from "@visactor/vutils";
2
+
3
+ const isIntersect = (top, bottom) => Math.ceil(top) > Math.floor(bottom), isXIntersect = ([a, b], [c, d]) => d > a && b > c;
4
+
5
+ function getIntersectionLength(range1, range2) {
6
+ const [start1, end1] = range1, [start2, end2] = range2, start = Math.max(start1, start2), end = Math.min(end1, end2);
7
+ return Math.max(0, end - start);
8
+ }
9
+
10
+ export function shiftY(texts, option) {
11
+ const {maxY: maxY = Number.MAX_VALUE, labelling: labelling, globalShiftY: globalShiftY = {
12
+ enable: !0,
13
+ maxIterations: 10,
14
+ maxError: .1,
15
+ padding: 1
16
+ }} = option, n = texts.length;
3
17
  if (n <= 1) return texts;
4
- const isIntersect = ([a, b], [c, d]) => d > a && b > c, textInformation = new Map, getY0 = text => textInformation.get(text).y0, getY = text => textInformation.get(text).y, getHeight = text => textInformation.get(text).height, getX1 = text => textInformation.get(text).x1, getX2 = text => textInformation.get(text).x2, setY = (text, y) => {
5
- textInformation.get(text).y = y;
18
+ const xMap = new Map, textInformation = new Map, getY1Initial = text => textInformation.get(text).y1Initial, getHeight = text => textInformation.get(text).height, getY1 = text => textInformation.get(text).y1, getX = text => textInformation.get(text).x, getX1 = text => textInformation.get(text).x1, getX2 = text => textInformation.get(text).x2, getAdjustAttempts = text => textInformation.get(text).attempts, setY1 = (text, y) => {
19
+ textInformation.get(text).y1 = y;
20
+ }, setAdjustAttempts = (text, attempts) => {
21
+ textInformation.get(text).attempts = attempts;
6
22
  };
23
+ function adjustPositionInOneGroup(texts) {
24
+ var text;
25
+ if (1 !== texts.length) for (let i = texts.length - 1; i > 0; i--) {
26
+ const curText = texts[i], upperText = texts[i - 1], lowerText = texts[i + 1];
27
+ if (isIntersect(getY1(upperText) + getHeight(upperText), getY1(curText))) {
28
+ const {y: y} = labelling(curText);
29
+ lowerText && isIntersect(y + getHeight(curText) / 2, getY1(lowerText)) || y + getHeight(curText) / 2 <= maxY && setY1(curText, getY1(curText) + y - (text = curText,
30
+ textInformation.get(text).y));
31
+ }
32
+ }
33
+ }
34
+ texts.sort(((a, b) => a.attribute.x - b.attribute.x));
7
35
  for (const text of texts) {
8
- const {y1: y1, y2: y2, x1: x1, x2: x2} = text.AABBBounds;
36
+ const {y1: y1, y2: y2, x1: x1, x2: x2} = text.AABBBounds, {x: x, y: y} = text.attribute;
9
37
  textInformation.set(text, {
10
- y0: y1,
11
- y: y1,
38
+ y1Initial: y1,
39
+ y1: y1,
40
+ y2: y2,
41
+ y: y,
12
42
  height: y2 - y1,
13
43
  x1: x1,
14
- x2: x2
44
+ x2: x2,
45
+ x: x,
46
+ attempts: 0
15
47
  });
48
+ let hasRange = !1;
49
+ for (const [range, xGroupTexts] of xMap) {
50
+ const {start: start, end: end} = range;
51
+ if (x1 >= start && x2 <= end) xGroupTexts.push(text), hasRange = !0; else if (isNumberClose(x, getX(xGroupTexts[0]), void 0, 5)) {
52
+ const newRange = {
53
+ start: Math.min(start, x1),
54
+ end: Math.max(end, x2)
55
+ };
56
+ xGroupTexts.push(text), xMap.set(newRange, xGroupTexts), xMap.delete(range), hasRange = !0;
57
+ } else if (getIntersectionLength([ start, end ], [ x1, x2 ]) / (end - start) > .5) {
58
+ const newRange = {
59
+ start: Math.min(start, x1),
60
+ end: Math.max(end, x2)
61
+ };
62
+ xGroupTexts.push(text), xMap.set(newRange, xGroupTexts), xMap.delete(range), hasRange = !0;
63
+ }
64
+ if (hasRange) break;
65
+ }
66
+ hasRange || xMap.set({
67
+ start: x1,
68
+ end: x2
69
+ }, [ text ]);
16
70
  }
17
- for (let iter = 0; iter < maxIterations; iter++) {
18
- texts.sort(((a, b) => getY(a) - getY(b)));
19
- let error = 0;
20
- for (let i = 0; i < n - 1; i++) {
21
- const curText = texts[i];
22
- let nextText, j = i + 1;
23
- for (;(nextText = texts[j]) && !isIntersect([ getX1(curText), getX2(curText) ], [ getX1(nextText), getX2(nextText) ]); ) j += 1;
24
- if (nextText) {
25
- const y0 = getY(curText), h0 = getHeight(curText), y1 = getY(nextText), delta = y1 - (y0 + h0);
26
- if (delta < padding) {
27
- const newDelta = (padding - delta) / 2;
28
- error = Math.max(error, newDelta), y1 + newDelta + getHeight(nextText) > maxY ? setY(curText, y0 - (padding - delta)) : y0 - newDelta < 0 ? setY(nextText, y1 + (padding - delta)) : (setY(curText, y0 - newDelta),
29
- setY(nextText, y1 + newDelta));
71
+ for (const xTexts of xMap.values()) xTexts.sort(((a, b) => getY1Initial(a) - getY1Initial(b))),
72
+ adjustPositionInOneGroup(xTexts);
73
+ if (!1 !== globalShiftY.enable) {
74
+ const {maxIterations: maxIterations = 10, maxError: maxError = .1, padding: padding = 1, maxAttempts: maxAttempts = 1e3, deltaYTolerance: deltaYTolerance = Number.MAX_VALUE} = globalShiftY;
75
+ for (let iter = 0; iter < maxIterations; iter++) {
76
+ texts.sort(((a, b) => getY1(a) - getY1(b)));
77
+ let error = 0;
78
+ for (let i = 0; i < n - 1; i++) {
79
+ const curText = texts[i];
80
+ if (getAdjustAttempts(curText) >= maxAttempts) continue;
81
+ let nextText, j = i + 1;
82
+ for (;(nextText = texts[j]) && !isXIntersect([ getX1(curText), getX2(curText) ], [ getX1(nextText), getX2(nextText) ]); ) j += 1;
83
+ if (nextText) {
84
+ const y1 = getY1(curText), h0 = getHeight(curText), nextY1 = getY1(nextText), delta = nextY1 - (y1 + h0);
85
+ if (delta < padding) {
86
+ const newDelta = (padding - delta) / 2;
87
+ if (error = Math.max(error, newDelta), y1 + newDelta + getHeight(nextText) > maxY) {
88
+ const newY1 = y1 - (padding - delta), curTextDelta = getY1Initial(curText) - newY1;
89
+ Math.abs(curTextDelta) <= deltaYTolerance && (setY1(curText, newY1), setAdjustAttempts(curText, getAdjustAttempts(curText) + 1));
90
+ } else if (y1 - newDelta < 0) {
91
+ const newY1 = nextY1 + (padding - delta), nextTextDelta = getY1Initial(nextText) - newY1;
92
+ Math.abs(nextTextDelta) <= deltaYTolerance && (setY1(nextText, newY1), setAdjustAttempts(nextText, getAdjustAttempts(nextText) + 1));
93
+ } else {
94
+ const newCurY1 = y1 - newDelta, curTextDelta = getY1Initial(curText) - newCurY1, newNextY1 = nextY1 + newDelta, nextTextDelta = getY1Initial(nextText) - newNextY1;
95
+ Math.abs(curTextDelta) <= deltaYTolerance && Math.abs(nextTextDelta) <= deltaYTolerance && (setY1(curText, newCurY1),
96
+ setY1(nextText, newNextY1), setAdjustAttempts(curText, getAdjustAttempts(curText) + 1),
97
+ setAdjustAttempts(nextText, getAdjustAttempts(nextText) + 1));
98
+ }
99
+ }
30
100
  }
31
101
  }
102
+ if (error < maxError) break;
32
103
  }
33
- if (error < maxError) break;
34
104
  }
35
105
  for (const text of texts) {
36
- const finalY = text.attribute.y + getY(text) - getY0(text);
106
+ const finalY = text.attribute.y + getY1(text) - getY1Initial(text);
37
107
  text.setAttribute("y", finalY);
38
108
  }
39
- return texts;
109
+ const result = [];
110
+ texts.sort(((a, b) => a.attribute.x - b.attribute.x));
111
+ let start = 0, end = texts.length - 1;
112
+ for (;start <= end; ) start === end ? result.push(texts[start]) : (result.push(texts[start]),
113
+ result.push(texts[end])), start++, end--;
114
+ return result;
40
115
  }
41
116
  //# sourceMappingURL=shiftY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/label/overlap/shiftY.ts"],"names":[],"mappings":"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","file":"shiftY.js","sourcesContent":["import type { IText } from '@visactor/vrender-core';\n\nexport interface IShiftYOption {\n maxIterations?: number;\n maxError?: number;\n padding?: number;\n maxY?: number;\n}\n\nexport function shiftY(texts: IText[], option: IShiftYOption = {}) {\n const { maxIterations = 10, maxError = 0.1, padding = 1, maxY = Number.MAX_VALUE } = option;\n\n const n = texts.length;\n if (n <= 1) {\n return texts;\n }\n\n const isIntersect = ([a, b]: [number, number], [c, d]: [number, number]) => {\n return d > a && b > c;\n };\n\n const textInformation = new Map<IText, { y0: number; y: number; height: number; x1: number; x2: number }>();\n\n // y0 : 初始位置\n // y : 最终位置\n // height : 高度\n // x1, x2 : 左右边界\n const getY0 = (text: IText) => textInformation.get(text).y0;\n const getY = (text: IText) => textInformation.get(text).y;\n const getHeight = (text: IText) => textInformation.get(text).height;\n const getX1 = (text: IText) => textInformation.get(text).x1;\n const getX2 = (text: IText) => textInformation.get(text).x2;\n const setY = (text: IText, y: number) => {\n textInformation.get(text).y = y;\n };\n\n for (const text of texts) {\n const { y1, y2, x1, x2 } = text.AABBBounds;\n textInformation.set(text, { y0: y1, y: y1, height: y2 - y1, x1, x2 });\n }\n\n for (let iter = 0; iter < maxIterations; iter++) {\n texts.sort((a, b) => getY(a) - getY(b));\n let error = 0;\n for (let i = 0; i < n - 1; i++) {\n const curText = texts[i];\n let j = i + 1;\n let nextText;\n while (\n (nextText = texts[j]) &&\n !isIntersect([getX1(curText), getX2(curText)], [getX1(nextText), getX2(nextText)])\n ) {\n j += 1;\n }\n if (nextText) {\n const y0 = getY(curText);\n const h0 = getHeight(curText);\n const y1 = getY(nextText);\n const delta = y1 - (y0 + h0);\n if (delta < padding) {\n const newDelta = (padding - delta) / 2;\n error = Math.max(error, newDelta);\n if (y1 + newDelta + getHeight(nextText) > maxY) {\n setY(curText, y0 - (padding - delta));\n } else if (y0 - newDelta < 0) {\n setY(nextText, y1 + (padding - delta));\n } else {\n setY(curText, y0 - newDelta);\n setY(nextText, y1 + newDelta);\n }\n }\n }\n }\n if (error < maxError) {\n break;\n }\n }\n\n for (const text of texts) {\n const finalY = text.attribute.y + getY(text) - getY0(text);\n text.setAttribute('y', finalY);\n }\n\n return texts;\n}\n"]}
1
+ {"version":3,"sources":["../src/label/overlap/shiftY.ts"],"names":[],"mappings":"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","file":"shiftY.js","sourcesContent":["import type { IText } from '@visactor/vrender-core';\nimport { isNumberClose } from '@visactor/vutils';\n\nexport interface IShiftYOption {\n labelling: (...args: any[]) => any;\n\n maxY?: number;\n globalShiftY?: {\n /**\n * 是否开启全局调整,开启后,所有文字会整体调整,否则只会按照 x 分组调整 top/bottom\n * @default true\n */\n enable?: boolean;\n /**\n * 最大迭代次数\n * @default 10\n */\n maxIterations?: number;\n /**\n * 最大误差\n * @default 0.1\n */\n maxError?: number;\n /**\n * 调整后 text 之间的 padding\n * @default 1\n */\n padding?: number;\n /**\n * 每个 text 最大被调整的次数\n * @default 1000\n */\n maxAttempts?: number;\n /**\n * 每个 text 调整的 y 坐标差值限制\n */\n deltaYTolerance?: number;\n };\n}\n\nconst isIntersect = (top: number, bottom: number) => {\n return Math.ceil(top) > Math.floor(bottom);\n};\n\nconst isXIntersect = ([a, b]: [number, number], [c, d]: [number, number]) => {\n return d > a && b > c;\n};\n\nfunction getIntersectionLength(range1: number[], range2: number[]) {\n const [start1, end1] = range1;\n const [start2, end2] = range2;\n\n const start = Math.max(start1, start2);\n const end = Math.min(end1, end2);\n\n return Math.max(0, end - start);\n}\n\nexport function shiftY(texts: IText[], option: IShiftYOption) {\n const {\n maxY = Number.MAX_VALUE,\n labelling,\n globalShiftY = { enable: true, maxIterations: 10, maxError: 0.1, padding: 1 }\n } = option;\n\n const n = texts.length;\n if (n <= 1) {\n return texts;\n }\n\n // 根据 x 坐标给 text 分组,存放信息到 map 中\n const xMap = new Map<{ start: number; end: number }, IText[]>();\n const textInformation = new Map<\n IText,\n {\n y1Initial: number;\n y1: number;\n y: number;\n y2: number;\n height: number;\n x1: number;\n x2: number;\n x: number;\n attempts: number;\n }\n >();\n\n const getY1Initial = (text: IText) => textInformation.get(text).y1Initial;\n const getHeight = (text: IText) => textInformation.get(text).height;\n const getY1 = (text: IText) => textInformation.get(text).y1;\n const getY = (text: IText) => textInformation.get(text).y;\n const getX = (text: IText) => textInformation.get(text).x;\n const getX1 = (text: IText) => textInformation.get(text).x1;\n const getX2 = (text: IText) => textInformation.get(text).x2;\n const getAdjustAttempts = (text: IText) => textInformation.get(text).attempts;\n\n const setY1 = (text: IText, y: number) => {\n textInformation.get(text).y1 = y;\n };\n\n const setAdjustAttempts = (text: IText, attempts: number) => {\n textInformation.get(text).attempts = attempts;\n };\n\n function adjustPositionInOneGroup(texts: IText[]) {\n if (texts.length === 1) {\n return;\n }\n // 从最后一个 text 向前遍历,如果与前一个 text 相交,则尝试放到下方(需要判断和前一个 text 是否相交,若相交则不能放到下方)\n for (let i = texts.length - 1; i > 0; i--) {\n const curText = texts[i];\n const upperText = texts[i - 1];\n const lowerText = texts[i + 1];\n\n // 当前 text 和上面一个 text 相交\n if (isIntersect(getY1(upperText) + getHeight(upperText), getY1(curText))) {\n const { y } = labelling(curText);\n // 挪动当前 text 后, 和下面一个 text 不相交\n if (!lowerText || !isIntersect(y + getHeight(curText) / 2, getY1(lowerText))) {\n if (y + getHeight(curText) / 2 <= maxY) {\n setY1(curText, getY1(curText) + y - getY(curText));\n }\n }\n }\n }\n }\n\n // 根据 x 坐标进行分组\n texts.sort((a, b) => a.attribute.x - b.attribute.x);\n for (const text of texts) {\n const { y1, y2, x1, x2 } = text.AABBBounds;\n const { x, y } = text.attribute;\n textInformation.set(text, { y1Initial: y1, y1, y2, y, height: y2 - y1, x1, x2, x, attempts: 0 });\n let hasRange = false;\n\n for (const [range, xGroupTexts] of xMap) {\n const { start, end } = range;\n // 1. x1,x2 在 start 和 end 范围内\n if (x1 >= start && x2 <= end) {\n xGroupTexts.push(text);\n hasRange = true;\n }\n // 2. x 坐标接近,相差在 5px 以内\n else if (isNumberClose(x, getX(xGroupTexts[0]), undefined, 5)) {\n // x 坐标相等,也纳入到一个分组中,并且要扩大分组 range\n const newRange = { start: Math.min(start, x1), end: Math.max(end, x2) };\n xGroupTexts.push(text);\n xMap.set(newRange, xGroupTexts);\n xMap.delete(range);\n hasRange = true;\n }\n // 3. 与区间相交范围 > 50%\n else if (getIntersectionLength([start, end], [x1, x2]) / (end - start) > 0.5) {\n const newRange = { start: Math.min(start, x1), end: Math.max(end, x2) };\n xGroupTexts.push(text);\n xMap.set(newRange, xGroupTexts);\n xMap.delete(range);\n hasRange = true;\n }\n\n if (hasRange) {\n break;\n }\n }\n\n if (!hasRange) {\n xMap.set({ start: x1, end: x2 }, [text]);\n }\n }\n\n // 对每个 x 坐标的 text 数组进行排序\n for (const xTexts of xMap.values()) {\n // 从上到下排序\n xTexts.sort((a, b) => getY1Initial(a) - getY1Initial(b));\n adjustPositionInOneGroup(xTexts);\n }\n\n // 整体调整一次 Y 坐标,进行散开\n if (globalShiftY.enable !== false) {\n const {\n maxIterations = 10,\n maxError = 0.1,\n padding = 1,\n maxAttempts = 1000,\n deltaYTolerance = Number.MAX_VALUE\n } = globalShiftY;\n for (let iter = 0; iter < maxIterations; iter++) {\n texts.sort((a, b) => getY1(a) - getY1(b));\n let error = 0;\n for (let i = 0; i < n - 1; i++) {\n const curText = texts[i];\n if (getAdjustAttempts(curText) >= maxAttempts) {\n continue;\n }\n let j = i + 1;\n let nextText;\n while (\n (nextText = texts[j]) &&\n !isXIntersect([getX1(curText), getX2(curText)], [getX1(nextText), getX2(nextText)])\n ) {\n j += 1;\n }\n if (nextText) {\n const y1 = getY1(curText);\n const h0 = getHeight(curText);\n const nextY1 = getY1(nextText);\n const delta = nextY1 - (y1 + h0);\n if (delta < padding) {\n const newDelta = (padding - delta) / 2;\n error = Math.max(error, newDelta);\n if (y1 + newDelta + getHeight(nextText) > maxY) {\n const newY1 = y1 - (padding - delta);\n const curTextDelta = getY1Initial(curText) - newY1;\n if (Math.abs(curTextDelta) <= deltaYTolerance) {\n setY1(curText, newY1);\n setAdjustAttempts(curText, getAdjustAttempts(curText) + 1);\n }\n } else if (y1 - newDelta < 0) {\n const newY1 = nextY1 + (padding - delta);\n const nextTextDelta = getY1Initial(nextText) - newY1;\n if (Math.abs(nextTextDelta) <= deltaYTolerance) {\n setY1(nextText, newY1);\n setAdjustAttempts(nextText, getAdjustAttempts(nextText) + 1);\n }\n } else {\n const newCurY1 = y1 - newDelta;\n const curTextDelta = getY1Initial(curText) - newCurY1;\n const newNextY1 = nextY1 + newDelta;\n const nextTextDelta = getY1Initial(nextText) - newNextY1;\n if (Math.abs(curTextDelta) <= deltaYTolerance && Math.abs(nextTextDelta) <= deltaYTolerance) {\n setY1(curText, newCurY1);\n setY1(nextText, newNextY1);\n setAdjustAttempts(curText, getAdjustAttempts(curText) + 1);\n setAdjustAttempts(nextText, getAdjustAttempts(nextText) + 1);\n }\n }\n }\n }\n }\n if (error < maxError) {\n break;\n }\n }\n }\n\n for (const text of texts) {\n const finalY = text.attribute.y + getY1(text) - getY1Initial(text);\n text.setAttribute('y', finalY);\n }\n\n const result = [];\n // 调整文字顺序,越靠前的越优先占据空间\n // texts 按照 x 进行排序,然后左右交替,保证首尾标签优先展示\n texts.sort((a, b) => a.attribute.x - b.attribute.x);\n let start = 0;\n let end = texts.length - 1;\n\n while (start <= end) {\n if (start === end) {\n result.push(texts[start]);\n } else {\n result.push(texts[start]);\n result.push(texts[end]);\n }\n start++;\n end--;\n }\n return result;\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { SliderAttributes } from '../../slider/type';
2
- import { LegendBaseAttributes } from '../type';
1
+ import type { SliderAttributes } from '../../slider/type';
2
+ import type { LegendBaseAttributes } from '../type';
3
3
  export type ColorLegendAttributes = {
4
4
  colors: string[];
5
5
  } & Omit<SliderAttributes, 'step' | 'range'> & LegendBaseAttributes;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/legend/color/type.ts"],"names":[],"mappings":"","file":"type.js","sourcesContent":["import { SliderAttributes } from '../../slider/type';\nimport { LegendBaseAttributes } from '../type';\nexport type ColorLegendAttributes = {\n /**\n * 图例的颜色\n */\n colors: string[];\n} & Omit<SliderAttributes, 'step' | 'range'> &\n LegendBaseAttributes;\n"]}
1
+ {"version":3,"sources":["../src/legend/color/type.ts"],"names":[],"mappings":"","file":"type.js","sourcesContent":["import type { SliderAttributes } from '../../slider/type';\nimport type { LegendBaseAttributes } from '../type';\nexport type ColorLegendAttributes = {\n /**\n * 图例的颜色\n */\n colors: string[];\n} & Omit<SliderAttributes, 'step' | 'range'> &\n LegendBaseAttributes;\n"]}
@@ -1,3 +1,4 @@
1
+ import type { IGroup } from '@visactor/vrender-core';
1
2
  import { LegendBase } from '../base';
2
3
  import type { DiscreteLegendAttrs, LegendItemDatum } from './type';
3
4
  import type { ComponentOptions } from '../../interface';
@@ -12,6 +13,8 @@ export declare class DiscreteLegend extends LegendBase<DiscreteLegendAttrs> {
12
13
  private _pagerComponent;
13
14
  private _lastActiveItem;
14
15
  private _itemContext;
16
+ private _scrollMask;
17
+ private _scrollMaskContext;
15
18
  static defaultAttributes: Partial<DiscreteLegendAttrs>;
16
19
  constructor(attributes: DiscreteLegendAttrs, options?: ComponentOptions);
17
20
  render(): void;
@@ -29,6 +32,7 @@ export declare class DiscreteLegend extends LegendBase<DiscreteLegendAttrs> {
29
32
  currentPage: number;
30
33
  totalPage: number;
31
34
  isScrollbar: boolean;
35
+ clipContainer: IGroup;
32
36
  };
33
37
  protected _renderContent(): void;
34
38
  protected _bindEvents(): void;
@@ -37,10 +41,13 @@ export declare class DiscreteLegend extends LegendBase<DiscreteLegendAttrs> {
37
41
  private _createPager;
38
42
  private _createScrollbar;
39
43
  private _updatePositionOfPager;
44
+ private _computeScrollbarDelta;
40
45
  private _updatePositionOfScrollbar;
41
46
  private _bindEventsOfPager;
42
47
  private _renderPager;
43
48
  private _renderScrollbar;
49
+ private renderScrollMask;
50
+ private updateScrollMask;
44
51
  private _renderPagerComponent;
45
52
  private _onHover;
46
53
  private _onUnHover;
@@ -8,7 +8,7 @@ var __rest = this && this.__rest || function(s, e) {
8
8
  return t;
9
9
  };
10
10
 
11
- import { merge, isEmpty, normalizePadding, get, isValid, isNil, isFunction, isArray, minInArray, throttle } from "@visactor/vutils";
11
+ import { merge, isEmpty, normalizePadding, get, isValid, isNil, isFunction, isArray, minInArray, throttle, isNumberClose, clamp, isObject } from "@visactor/vutils";
12
12
 
13
13
  import { graphicCreator } from "@visactor/vrender-core";
14
14
 
@@ -153,7 +153,8 @@ export class DiscreteLegend extends LegendBase {
153
153
  items: legendItems,
154
154
  isHorizontal: isHorizontal,
155
155
  totalPage: 1 / 0,
156
- isScrollbar: pager && "scrollbar" === pager.type
156
+ isScrollbar: pager && "scrollbar" === pager.type,
157
+ clipContainer: void 0
157
158
  }, this._itemContext = this._renderItems();
158
159
  let pagerRendered = !1;
159
160
  this._itemContext.doWrap && autoPage && this._itemContext.pages > this._itemContext.maxPages && (pagerRendered = this._renderPagerComponent()),
@@ -164,8 +165,15 @@ export class DiscreteLegend extends LegendBase {
164
165
  if (this.attribute.disableTriggerEvent) return;
165
166
  if (!this._itemsContainer) return;
166
167
  const {hover: hover = !0, select: select = !0} = this.attribute;
167
- hover && (this._itemsContainer.addEventListener("pointermove", this._onHover), this._itemsContainer.addEventListener("pointerleave", this._onUnHover)),
168
- select && this._itemsContainer.addEventListener("pointerdown", this._onClick);
168
+ if (hover) {
169
+ let trigger = "pointermove", triggerOff = "pointerleave";
170
+ isObject(hover) && (hover.trigger && (trigger = hover.trigger), hover.triggerOff && (triggerOff = hover.triggerOff)),
171
+ this._itemsContainer.addEventListener(trigger, this._onHover), this._itemsContainer.addEventListener(triggerOff, this._onUnHover);
172
+ }
173
+ if (select) {
174
+ let trigger = "pointerdown";
175
+ isObject(select) && select.trigger && (trigger = select.trigger), this._itemsContainer.addEventListener(trigger, this._onClick);
176
+ }
169
177
  }
170
178
  _autoEllipsis(autoEllipsisStrategy, layoutWidth, labelShape, valueShape) {
171
179
  var _a, _b;
@@ -307,12 +315,12 @@ export class DiscreteLegend extends LegendBase {
307
315
  direction: "horizontal",
308
316
  disableTriggerEvent: disableTriggerEvent,
309
317
  range: [ 0, .5 ],
310
- height: 12
318
+ height: !1 === compStyle.visible ? 0 : 12
311
319
  }, compStyle), {
312
320
  width: compSize
313
321
  })) : new ScrollBar(Object.assign(Object.assign({
314
322
  direction: "vertical",
315
- width: 12,
323
+ width: !1 === compStyle.visible ? 0 : 12,
316
324
  range: [ 0, .5 ]
317
325
  }, compStyle), {
318
326
  height: compSize,
@@ -337,9 +345,15 @@ export class DiscreteLegend extends LegendBase {
337
345
  });
338
346
  }
339
347
  }
348
+ _computeScrollbarDelta() {
349
+ const {isHorizontal: isHorizontal, clipContainer: clipContainer} = this._itemContext, itemContainerBounds = this._itemsContainer.AABBBounds, clipContainerBounds = clipContainer.AABBBounds;
350
+ let delta, innerViewSize;
351
+ return isHorizontal ? (innerViewSize = clipContainerBounds.width(), delta = innerViewSize / itemContainerBounds.width()) : (innerViewSize = clipContainerBounds.height(),
352
+ delta = innerViewSize / itemContainerBounds.height()), delta;
353
+ }
340
354
  _updatePositionOfScrollbar(contentWidth, contentHeight, renderStartY) {
341
- const {currentPage: currentPage, totalPage: totalPage, isHorizontal: isHorizontal} = this._itemContext;
342
- this._pagerComponent.setScrollRange([ (currentPage - 1) / totalPage, currentPage / totalPage ]),
355
+ const {isHorizontal: isHorizontal, currentPage: currentPage, totalPage: totalPage} = this._itemContext, start = (currentPage - 1) / totalPage;
356
+ this._pagerComponent.setScrollRange([ start, start + this._computeScrollbarDelta() ]),
343
357
  isHorizontal ? this._pagerComponent.setAttributes({
344
358
  x: 0,
345
359
  y: renderStartY + contentHeight
@@ -352,20 +366,32 @@ export class DiscreteLegend extends LegendBase {
352
366
  const pager = this.attribute.pager || {}, {animation: animation = !0, animationDuration: animationDuration = 450, animationEasing: animationEasing = "quadIn"} = pager, pageParser = this._itemContext.isScrollbar ? e => {
353
367
  const {value: value} = e.detail;
354
368
  let newPage;
355
- return 0 === value[0] ? newPage = 1 : 1 === value[1] ? newPage = this._itemContext.totalPage : (newPage = value[0] * this._itemContext.totalPage,
356
- pager.scrollByPosition ? newPage += 1 : newPage = Math.floor(newPage) + 1), newPage;
369
+ return newPage = 0 === value[0] ? 1 : 1 === value[1] ? this._itemContext.totalPage : value[0] * this._itemContext.totalPage + 1,
370
+ newPage;
357
371
  } : e => e.detail.current, onScroll = e => {
358
372
  const scrollComponent = this._pagerComponent, preScrollRange = scrollComponent.getScrollRange(), {direction: direction} = scrollComponent.attribute, {width: width, height: height} = scrollComponent.getSliderRenderBounds(), currentScrollValue = "vertical" === direction ? e.deltaY / height : e.deltaX / width;
359
- scrollComponent.setScrollRange([ preScrollRange[0] + currentScrollValue, preScrollRange[1] + currentScrollValue ], !0);
373
+ scrollComponent.setScrollRange([ preScrollRange[0] + currentScrollValue, preScrollRange[1] + currentScrollValue ], !0),
374
+ this.updateScrollMask();
360
375
  }, onPaging = e => {
361
376
  const newPage = pageParser(e);
362
377
  if (newPage !== this._itemContext.currentPage) {
363
378
  if (this._itemContext.currentPage = newPage, this._itemContext && this._itemContext.startIndex < this._itemContext.items.length) {
364
379
  this._renderItems();
365
380
  const newTotalPage = Math.ceil(this._itemContext.pages / this._itemContext.maxPages);
366
- this._itemContext.totalPage = newTotalPage, this._pagerComponent.setScrollRange([ (newPage - 1) / newTotalPage, newPage / newTotalPage ]);
381
+ if (this._itemContext.totalPage = newTotalPage, this._itemContext.isScrollbar && this._pagerComponent) {
382
+ const newDelta = this._computeScrollbarDelta(), [start] = this._pagerComponent.getScrollRange();
383
+ this._pagerComponent.setScrollRange([ start, start + newDelta ]);
384
+ }
367
385
  }
368
- animation ? this._itemsContainer.animate().to({
386
+ if (this._itemContext.isScrollbar) {
387
+ const [start] = this._pagerComponent.getScrollRange();
388
+ let containerSize;
389
+ containerSize = this._itemContext.isHorizontal ? this._itemsContainer.AABBBounds.width() : this._itemsContainer.AABBBounds.height();
390
+ const startOffset = containerSize * start;
391
+ this.updateScrollMask(), animation ? this._itemsContainer.animate().to({
392
+ [channel]: -startOffset
393
+ }, animationDuration, animationEasing) : this._itemsContainer.setAttribute(channel, -startOffset);
394
+ } else animation ? this._itemsContainer.animate().to({
369
395
  [channel]: -(newPage - 1) * pageSize
370
396
  }, animationDuration, animationEasing) : this._itemsContainer.setAttribute(channel, -(newPage - 1) * pageSize);
371
397
  }
@@ -421,18 +447,20 @@ export class DiscreteLegend extends LegendBase {
421
447
  clip: !0,
422
448
  pickable: !1
423
449
  });
424
- return clipGroup.add(itemsContainer), this._innerView.add(clipGroup), this._bindEventsOfPager(isHorizontal ? compHeight + spaceRow : compWidth + spaceCol, isHorizontal ? "y" : "x"),
450
+ return clipGroup.add(itemsContainer), this._innerView.add(clipGroup), this._itemContext.clipContainer = clipGroup,
451
+ this._bindEventsOfPager(isHorizontal ? compHeight + spaceRow : compWidth + spaceCol, isHorizontal ? "y" : "x"),
425
452
  !0;
426
453
  }
427
454
  _renderScrollbar() {
455
+ var _a;
428
456
  const renderStartY = this._title ? this._title.AABBBounds.height() + get(this.attribute, "title.space", 8) : 0, {maxWidth: maxWidth, item: item = {}, pager: pager = {}} = this.attribute, {spaceCol: spaceCol = DEFAULT_ITEM_SPACE_COL, spaceRow: spaceRow = DEFAULT_ITEM_SPACE_ROW} = item, itemsContainer = this._itemsContainer, {space: pagerSpace = DEFAULT_PAGER_SPACE, defaultCurrent: defaultCurrent = 1} = pager, compStyle = __rest(pager, [ "space", "defaultCurrent" ]), {isHorizontal: isHorizontal} = this._itemContext, maxHeight = this._contentMaxHeight;
429
- let comp, compSize = 0, contentWidth = 0, contentHeight = 0, startY = 0, pages = 1;
430
- if (isHorizontal) compSize = maxWidth, contentWidth = maxWidth, contentHeight = this._itemHeight,
431
- comp = this._createScrollbar(compStyle, compSize), this._pagerComponent = comp,
432
- this._innerView.add(comp), this._updatePositionOfScrollbar(contentWidth, contentHeight, renderStartY); else {
433
- if (compSize = maxHeight, comp = this._createScrollbar(compStyle, compSize), this._pagerComponent = comp,
434
- this._innerView.add(comp), contentHeight = maxHeight - renderStartY, contentWidth = this._itemMaxWidth,
435
- contentHeight <= 0) return this._innerView.removeChild(comp), !1;
457
+ let comp, contentWidth = 0, contentHeight = 0, startY = 0, pages = 1;
458
+ if (isHorizontal) contentWidth = maxWidth, contentHeight = this._itemHeight, comp = this._createScrollbar(compStyle, contentWidth),
459
+ this._pagerComponent = comp, this._innerView.add(comp); else {
460
+ if (contentHeight = maxHeight - renderStartY, contentWidth = this._itemMaxWidth,
461
+ comp = this._createScrollbar(compStyle, contentHeight), this._pagerComponent = comp,
462
+ this._innerView.add(comp), contentHeight <= 0) return this._innerView.removeChild(comp),
463
+ !1;
436
464
  const items = itemsContainer.getChildren(), itemsHeightArr = items.map((item => item.attribute.height));
437
465
  if (1 === itemsHeightArr.length || itemsHeightArr.every((entry => entry === itemsHeightArr[0]))) {
438
466
  const itemHeight = itemsHeightArr[0], maxContentHeight = contentHeight, pageItemsCount = Math.floor(maxContentHeight / (spaceRow + itemHeight));
@@ -443,9 +471,15 @@ export class DiscreteLegend extends LegendBase {
443
471
  prePages !== pages && index === itemsContainer.getChildren().length - 1 && startY - contentHeight >= 1 / 3 * height && (contentHeight = preStartY + height,
444
472
  pages -= 1);
445
473
  }));
446
- this._itemContext.totalPage = pages, this._itemContext.pages = pages, this._updatePositionOfScrollbar(contentWidth, contentHeight, renderStartY);
474
+ this._itemContext.totalPage = pages, this._itemContext.pages = pages;
475
+ }
476
+ if (defaultCurrent > 1) if (isHorizontal) {
477
+ const maxOffset = this._itemsContainer.AABBBounds.width() - contentWidth;
478
+ itemsContainer.setAttribute("x", -Math.min((defaultCurrent - 1) * (contentWidth + spaceCol), maxOffset));
479
+ } else {
480
+ const maxOffset = this._itemsContainer.AABBBounds.height() - contentHeight;
481
+ itemsContainer.setAttribute("y", -Math.min((defaultCurrent - 1) * (contentHeight + spaceRow), maxOffset));
447
482
  }
448
- defaultCurrent > 1 && (isHorizontal ? itemsContainer.setAttribute("x", -(defaultCurrent - 1) * (contentWidth + spaceCol)) : itemsContainer.setAttribute("y", -(defaultCurrent - 1) * (contentHeight + spaceRow)));
449
483
  const clipGroup = graphicCreator.group({
450
484
  x: 0,
451
485
  y: renderStartY,
@@ -454,9 +488,57 @@ export class DiscreteLegend extends LegendBase {
454
488
  clip: !0,
455
489
  pickable: !1
456
490
  });
457
- return clipGroup.add(itemsContainer), this._innerView.add(clipGroup), this._bindEventsOfPager(isHorizontal ? contentWidth : contentHeight, isHorizontal ? "x" : "y"),
491
+ return clipGroup.add(itemsContainer), this._innerView.add(clipGroup), this._itemContext.clipContainer = clipGroup,
492
+ this._updatePositionOfScrollbar(contentWidth, contentHeight, renderStartY), (null === (_a = pager.scrollMask) || void 0 === _a ? void 0 : _a.visible) && this.renderScrollMask(clipGroup),
493
+ this._bindEventsOfPager(isHorizontal ? contentWidth : contentHeight, isHorizontal ? "x" : "y"),
458
494
  !0;
459
495
  }
496
+ renderScrollMask(clipGroup) {
497
+ const {scrollMask: scrollMask = {}} = this.attribute.pager, {visible: visible = !0, gradientLength: gradientLength = 16, gradientStops: gradientStops} = scrollMask;
498
+ if (!visible || !gradientStops) return;
499
+ const width = clipGroup.AABBBounds.width(), height = clipGroup.AABBBounds.height(), totalLength = this._itemContext.isHorizontal ? width : height, startStops = gradientStops.map((stop => ({
500
+ offset: gradientLength * stop.offset / totalLength,
501
+ color: stop.color
502
+ }))), endStops = gradientStops.map((stop => ({
503
+ offset: (totalLength - gradientLength * stop.offset) / totalLength,
504
+ color: stop.color
505
+ }))), mask = graphicCreator.rect({
506
+ x: 0,
507
+ y: 0,
508
+ width: width,
509
+ height: height
510
+ });
511
+ this._scrollMask = mask, this._scrollMaskContext = {
512
+ startStops: startStops,
513
+ endStops: endStops
514
+ }, this.updateScrollMask(), clipGroup.add(mask);
515
+ }
516
+ updateScrollMask() {
517
+ if (!this._scrollMask || !this._pagerComponent) return;
518
+ if (!this._itemContext.isScrollbar) return;
519
+ const [start, end] = this._pagerComponent.getScrollRange(), stops = [];
520
+ isNumberClose(clamp(end, 0, 1), 1) || stops.push(...this._scrollMaskContext.endStops),
521
+ isNumberClose(clamp(start, 0, 1), 0) || stops.push(...this._scrollMaskContext.startStops),
522
+ stops.length && (this._itemContext.isHorizontal ? this._scrollMask.setAttributes({
523
+ fill: {
524
+ gradient: "linear",
525
+ x0: 0,
526
+ y0: 0,
527
+ x1: 1,
528
+ y1: 0,
529
+ stops: stops
530
+ }
531
+ }) : this._scrollMask.setAttributes({
532
+ fill: {
533
+ gradient: "linear",
534
+ x0: 0,
535
+ y0: 0,
536
+ x1: 0,
537
+ y1: 1,
538
+ stops: stops
539
+ }
540
+ }));
541
+ }
460
542
  _renderPagerComponent() {
461
543
  return this._itemContext.isScrollbar ? this._renderScrollbar() : this._renderPager(),
462
544
  !0;