evui 3.4.206 → 3.4.208

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 (162) hide show
  1. package/README.md +18 -33
  2. package/dist/404.html +44 -0
  3. package/dist/favicon.ico +0 -0
  4. package/dist/index.js +22645 -0
  5. package/dist/index.umd.cjs +28 -0
  6. package/dist/style.css +1 -0
  7. package/package.json +46 -43
  8. package/dist/evui.common.js +0 -63678
  9. package/dist/evui.common.js.map +0 -1
  10. package/dist/evui.umd.js +0 -63688
  11. package/dist/evui.umd.js.map +0 -1
  12. package/dist/evui.umd.min.js +0 -2
  13. package/dist/evui.umd.min.js.map +0 -1
  14. package/dist/img/EVUI.b82ee81a.svg +0 -293
  15. package/src/assets/logo.png +0 -0
  16. package/src/common/emitter.js +0 -20
  17. package/src/common/utils.bignumber.js +0 -67
  18. package/src/common/utils.debounce.js +0 -223
  19. package/src/common/utils.js +0 -151
  20. package/src/common/utils.table.js +0 -78
  21. package/src/common/utils.throttle.js +0 -83
  22. package/src/common/utils.tree.js +0 -18
  23. package/src/components/button/Button.vue +0 -195
  24. package/src/components/button/index.js +0 -7
  25. package/src/components/buttonGroup/ButtonGroup.vue +0 -11
  26. package/src/components/buttonGroup/index.js +0 -7
  27. package/src/components/calendar/Calendar.vue +0 -725
  28. package/src/components/calendar/index.js +0 -7
  29. package/src/components/calendar/uses.js +0 -1410
  30. package/src/components/chart/Chart.vue +0 -363
  31. package/src/components/chart/ChartToolbar.vue +0 -52
  32. package/src/components/chart/chart.core.js +0 -1170
  33. package/src/components/chart/chartZoom.core.js +0 -540
  34. package/src/components/chart/element/element.bar.js +0 -672
  35. package/src/components/chart/element/element.bar.time.js +0 -166
  36. package/src/components/chart/element/element.heatmap.js +0 -743
  37. package/src/components/chart/element/element.line.js +0 -611
  38. package/src/components/chart/element/element.pie.js +0 -197
  39. package/src/components/chart/element/element.scatter.js +0 -320
  40. package/src/components/chart/element/element.tip.js +0 -717
  41. package/src/components/chart/helpers/helpers.canvas.js +0 -265
  42. package/src/components/chart/helpers/helpers.constant.js +0 -235
  43. package/src/components/chart/helpers/helpers.util.js +0 -400
  44. package/src/components/chart/index.js +0 -9
  45. package/src/components/chart/model/index.js +0 -50
  46. package/src/components/chart/model/model.series.js +0 -125
  47. package/src/components/chart/model/model.store.js +0 -1427
  48. package/src/components/chart/plugins/plugins.interaction.js +0 -1655
  49. package/src/components/chart/plugins/plugins.legend.gradient.js +0 -606
  50. package/src/components/chart/plugins/plugins.legend.js +0 -1543
  51. package/src/components/chart/plugins/plugins.pie.js +0 -254
  52. package/src/components/chart/plugins/plugins.scrollbar.js +0 -732
  53. package/src/components/chart/plugins/plugins.title.js +0 -61
  54. package/src/components/chart/plugins/plugins.tooltip.js +0 -1041
  55. package/src/components/chart/scale/scale.js +0 -951
  56. package/src/components/chart/scale/scale.linear.js +0 -268
  57. package/src/components/chart/scale/scale.logarithmic.js +0 -135
  58. package/src/components/chart/scale/scale.step.js +0 -430
  59. package/src/components/chart/scale/scale.time.category.js +0 -338
  60. package/src/components/chart/scale/scale.time.js +0 -49
  61. package/src/components/chart/style/chart.scss +0 -405
  62. package/src/components/chart/uses.js +0 -721
  63. package/src/components/chartBrush/ChartBrush.vue +0 -323
  64. package/src/components/chartBrush/chartBrush.core.js +0 -691
  65. package/src/components/chartBrush/index.js +0 -9
  66. package/src/components/chartBrush/uses.js +0 -23
  67. package/src/components/chartGroup/ChartGroup.vue +0 -144
  68. package/src/components/chartGroup/index.js +0 -9
  69. package/src/components/chartGroup/style/chartGroup.scss +0 -5
  70. package/src/components/chartGroup/uses.js +0 -53
  71. package/src/components/checkbox/Checkbox.vue +0 -229
  72. package/src/components/checkbox/index.js +0 -7
  73. package/src/components/checkboxGroup/CheckboxGroup.vue +0 -44
  74. package/src/components/checkboxGroup/index.js +0 -7
  75. package/src/components/contextMenu/ContextMenu.vue +0 -95
  76. package/src/components/contextMenu/MenuList.vue +0 -182
  77. package/src/components/contextMenu/index.js +0 -7
  78. package/src/components/contextMenu/uses.js +0 -223
  79. package/src/components/datePicker/DatePicker.vue +0 -504
  80. package/src/components/datePicker/index.js +0 -7
  81. package/src/components/datePicker/uses.js +0 -460
  82. package/src/components/grid/Grid.vue +0 -1535
  83. package/src/components/grid/GridColumnSetting.vue +0 -358
  84. package/src/components/grid/GridFilterSetting.vue +0 -323
  85. package/src/components/grid/GridPagination.vue +0 -75
  86. package/src/components/grid/GridSummary.vue +0 -314
  87. package/src/components/grid/GridToolbar.vue +0 -35
  88. package/src/components/grid/icon/icon-option-button.vue +0 -17
  89. package/src/components/grid/icon/icon-sort-button.vue +0 -67
  90. package/src/components/grid/index.js +0 -11
  91. package/src/components/grid/style/grid.scss +0 -417
  92. package/src/components/grid/uses.js +0 -1629
  93. package/src/components/icon/Icon.vue +0 -53
  94. package/src/components/icon/index.js +0 -8
  95. package/src/components/inputNumber/InputNumber.vue +0 -212
  96. package/src/components/inputNumber/index.js +0 -7
  97. package/src/components/inputNumber/uses.js +0 -217
  98. package/src/components/loading/Loading.vue +0 -125
  99. package/src/components/loading/index.js +0 -7
  100. package/src/components/menu/Menu.vue +0 -79
  101. package/src/components/menu/MenuItem.vue +0 -201
  102. package/src/components/menu/index.js +0 -7
  103. package/src/components/message/Message.vue +0 -229
  104. package/src/components/message/index.js +0 -34
  105. package/src/components/messageBox/MessageBox.vue +0 -358
  106. package/src/components/messageBox/index.js +0 -22
  107. package/src/components/notification/Notification.vue +0 -316
  108. package/src/components/notification/index.js +0 -49
  109. package/src/components/pagination/Pagination.vue +0 -317
  110. package/src/components/pagination/index.js +0 -7
  111. package/src/components/pagination/pageButton.vue +0 -31
  112. package/src/components/progress/Progress.vue +0 -139
  113. package/src/components/progress/index.js +0 -7
  114. package/src/components/radio/Radio.vue +0 -159
  115. package/src/components/radio/index.js +0 -7
  116. package/src/components/radioGroup/RadioGroup.vue +0 -41
  117. package/src/components/radioGroup/index.js +0 -7
  118. package/src/components/scheduler/Scheduler.vue +0 -149
  119. package/src/components/scheduler/index.js +0 -7
  120. package/src/components/scheduler/uses.js +0 -183
  121. package/src/components/select/Select.vue +0 -556
  122. package/src/components/select/index.js +0 -7
  123. package/src/components/select/uses.js +0 -379
  124. package/src/components/slider/Slider.vue +0 -505
  125. package/src/components/slider/index.js +0 -7
  126. package/src/components/slider/uses.js +0 -391
  127. package/src/components/tabPanel/TabPanel.vue +0 -74
  128. package/src/components/tabPanel/index.js +0 -7
  129. package/src/components/tabs/Tabs.vue +0 -517
  130. package/src/components/tabs/index.js +0 -7
  131. package/src/components/textField/TextField.vue +0 -399
  132. package/src/components/textField/index.js +0 -7
  133. package/src/components/timePicker/TimePicker.vue +0 -364
  134. package/src/components/timePicker/index.js +0 -7
  135. package/src/components/toggle/Toggle.vue +0 -115
  136. package/src/components/toggle/index.js +0 -7
  137. package/src/components/tree/Tree.vue +0 -338
  138. package/src/components/tree/TreeNode.vue +0 -293
  139. package/src/components/tree/index.js +0 -7
  140. package/src/components/treeGrid/TreeGrid.vue +0 -1074
  141. package/src/components/treeGrid/TreeGridNode.vue +0 -349
  142. package/src/components/treeGrid/TreeGridToolbar.vue +0 -35
  143. package/src/components/treeGrid/icon/icon-tree.png +0 -0
  144. package/src/components/treeGrid/index.js +0 -9
  145. package/src/components/treeGrid/style/treeGrid.scss +0 -277
  146. package/src/components/treeGrid/uses.js +0 -1178
  147. package/src/components/window/Window.vue +0 -329
  148. package/src/components/window/index.js +0 -7
  149. package/src/components/window/uses.js +0 -908
  150. package/src/directives/clickoutside.js +0 -90
  151. package/src/main.js +0 -120
  152. package/src/style/components/input.scss +0 -108
  153. package/src/style/functions.scss +0 -3
  154. package/src/style/index.scss +0 -6
  155. package/src/style/lib/fonts/EVUI.eot +0 -0
  156. package/src/style/lib/fonts/EVUI.svg +0 -293
  157. package/src/style/lib/fonts/EVUI.ttf +0 -0
  158. package/src/style/lib/fonts/EVUI.woff +0 -0
  159. package/src/style/lib/icon.css +0 -888
  160. package/src/style/mixins.scss +0 -94
  161. package/src/style/themes.scss +0 -69
  162. package/src/style/variables.scss +0 -22
@@ -1,1041 +0,0 @@
1
- import { convertToPercent } from '@/common/utils';
2
- import debounce from '@/common/utils.debounce';
3
- import { inRange } from 'lodash-es';
4
- import Canvas from '../helpers/helpers.canvas';
5
- import Util from '../helpers/helpers.util';
6
-
7
- const LINE_SPACING = 8;
8
- const VALUE_MARGIN = 50;
9
- const SCROLL_WIDTH = 17;
10
- const BODY_PADDING = 8;
11
-
12
- const modules = {
13
- /**
14
- * Create tooltip DOM
15
- *
16
- * @returns {undefined}
17
- */
18
- createTooltipDOM() {
19
- this.tooltipDOM = document.createElement('div');
20
- this.tooltipDOM.className = 'ev-chart-tooltip';
21
-
22
- this.tooltipHeaderDOM = document.createElement('div');
23
- this.tooltipHeaderDOM.className = 'ev-chart-tooltip-header';
24
-
25
- this.tooltipBodyDOM = document.createElement('div');
26
- this.tooltipBodyDOM.className = 'ev-chart-tooltip-body';
27
-
28
- this.tooltipCanvas = document.createElement('canvas');
29
- this.tooltipCanvas.className = 'ev-chart-tooltip-canvas';
30
- this.tooltipCtx = this.tooltipCanvas.getContext('2d');
31
-
32
- this.tooltipDOM.style.display = 'none';
33
-
34
- if (!this.options.tooltip?.formatter?.html) {
35
- this.setDefaultTooltipLayout();
36
- }
37
-
38
- document.body.appendChild(this.tooltipDOM);
39
-
40
- if (this.options.tooltip.debouncedHide) {
41
- this.hideTooltipDOM = debounce(() => {
42
- this.tooltipDOM.style.display = 'none';
43
- }, 200);
44
- } else {
45
- this.hideTooltipDOM = () => {
46
- this.tooltipDOM.style.display = 'none';
47
- };
48
- }
49
- this.isInitTooltip = true;
50
- },
51
-
52
- setDefaultTooltipLayout() {
53
- this.tooltipBodyDOM.appendChild(this.tooltipCanvas);
54
- this.tooltipDOM.appendChild(this.tooltipHeaderDOM);
55
- this.tooltipDOM.appendChild(this.tooltipBodyDOM);
56
- },
57
-
58
- /**
59
- * get Tooltip's font style by Type ('title' | 'contents')
60
- * @param {string} type 'title' | 'contents'
61
- * @returns {string}
62
- */
63
- getFontStyle(type) {
64
- const opt = this.options?.tooltip;
65
- const fontSize = opt?.fontSize?.[type] ?? 14;
66
- const fontFamily = opt?.fontFamily ?? 'Roboto';
67
-
68
- return `normal normal lighter ${Math.max(fontSize, 0)}px ${fontFamily}`;
69
- },
70
-
71
- getTextHeight() {
72
- return (this.options?.tooltip?.fontSize?.contents ?? 14) + 6;
73
- },
74
-
75
- getColorMargin() {
76
- return (this.options?.tooltip?.fontSize?.contents ?? 14) + 2;
77
- },
78
-
79
- getBoxPadding() {
80
- const {
81
- top = 0,
82
- right = 20,
83
- bottom = 3,
84
- left = 16,
85
- } = this.options?.tooltip?.rowPadding ?? {};
86
-
87
- return {
88
- t: top,
89
- l: left,
90
- b: bottom,
91
- r: right,
92
- };
93
- },
94
-
95
- /**
96
- * Set tooltip DOM's position and style
97
- * @param {object} hitInfo value and mouse position touched
98
- * @param {object} e mousemove callback
99
- *
100
- * @returns {object} tooltip layout information
101
- */
102
- setTooltipLayoutPosition(hitInfo, e) {
103
- const ctx = this.tooltipCtx;
104
- const mouseX = e.pageX;
105
- const mouseY = e.pageY;
106
- const items = hitInfo.items;
107
- const [maxSeries, maxValue] = hitInfo.maxTip;
108
- const seriesKeys = Object.keys(items);
109
- const seriesLen = seriesKeys.length;
110
- const boxPadding = this.getBoxPadding();
111
- const opt = this.options.tooltip;
112
- const seriesColorMarginRight = this.getColorMargin();
113
-
114
- // Draw hidden tooltip header DOM to calculate height
115
- const sId = hitInfo.hitId;
116
- const hitItem = items[sId].data;
117
- const hitAxis = items[sId].axis;
118
- const titleFormatter = opt.formatter?.title;
119
-
120
- if (this.axesX.length && this.axesY.length && opt.showHeader) {
121
- if (titleFormatter) {
122
- this.tooltipHeaderDOM.textContent = titleFormatter({
123
- x: hitItem.x,
124
- y: hitItem.y,
125
- });
126
- } else {
127
- this.tooltipHeaderDOM.textContent = this.options.horizontal
128
- ? this.axesY[hitAxis.y].getLabelFormat(hitItem.y)
129
- : this.axesX[hitAxis.x].getLabelFormat(hitItem.x);
130
- }
131
- }
132
-
133
- if (opt.textOverflow) {
134
- this.tooltipHeaderDOM.classList.add(`ev-chart-tooltip-header--${opt.textOverflow}`);
135
- }
136
-
137
- this.tooltipHeaderDOM.style.visibility = 'hidden';
138
-
139
- // calculate and decide width of canvas El(contentsWidth)
140
- ctx.save();
141
- ctx.font = this.getFontStyle('contents');
142
- const isHorizontal = !!this.options.horizontal;
143
- const label = isHorizontal ? items[hitInfo.hitId]?.data?.y : items[hitInfo.hitId]?.data?.x;
144
- const tooltipValue = label?.length > maxSeries.length ? label : maxSeries;
145
- const nw = Math.round(ctx.measureText(tooltipValue).width);
146
- const vw = Math.round(ctx.measureText(maxValue).width);
147
- const expectedContentsWidth = nw + vw + boxPadding.l + boxPadding.r
148
- + seriesColorMarginRight + VALUE_MARGIN + SCROLL_WIDTH;
149
- const contentsWidth = expectedContentsWidth > opt.maxWidth
150
- ? opt.maxWidth
151
- : expectedContentsWidth;
152
-
153
-
154
- // Calculate height of canvas El(tooltip body El) with wrapped line count
155
- let textLineCnt = opt.textOverflow === 'wrap' ? 0 : seriesLen;
156
-
157
- if (opt.textOverflow === 'wrap') {
158
- const seriesNameSpaceWidth = opt.maxWidth - (Math.round(ctx.measureText(maxValue).width)
159
- + boxPadding.l + boxPadding.r + seriesColorMarginRight + VALUE_MARGIN + SCROLL_WIDTH);
160
-
161
- // count wrap line
162
- const seriesNames = Object.values(items).map(s => s.name);
163
- seriesNames.forEach((name) => {
164
- if (ctx.measureText(name).width > seriesNameSpaceWidth) {
165
- let line = '';
166
- for (let jx = 0; jx < name.length; jx++) {
167
- const char = name[jx];
168
- const temp = `${line}${char}`;
169
- if (ctx.measureText(temp).width > seriesNameSpaceWidth) {
170
- line = char;
171
- textLineCnt += 1;
172
- } else {
173
- line = temp;
174
- }
175
- }
176
- }
177
- textLineCnt += 1;
178
- });
179
- ctx.restore();
180
- }
181
-
182
-
183
- // Calculate height of canvas El(tooltip body El) with useScrollbar, maxHeight option
184
- const expectedContentsHeight = boxPadding.t
185
- + (textLineCnt * this.getTextHeight())
186
- + (seriesLen * LINE_SPACING)
187
- + boxPadding.b;
188
-
189
- let contentsHeight;
190
- if (opt.useScrollbar && expectedContentsHeight > opt.maxHeight) {
191
- this.tooltipBodyDOM.style.overflowY = 'auto';
192
- contentsHeight = opt.maxHeight;
193
- } else {
194
- this.tooltipBodyDOM.style.overflowY = 'hidden';
195
- contentsHeight = expectedContentsHeight;
196
- }
197
-
198
- // set width / height to all DOM elements (canvas, tooltip(wrapper), header, body)
199
- this.tooltipCanvas.width = contentsWidth * this.pixelRatio;
200
- this.tooltipCanvas.height = expectedContentsHeight * this.pixelRatio;
201
- this.tooltipCanvas.style.width = `${contentsWidth}px`;
202
- this.tooltipCanvas.style.height = `${expectedContentsHeight}px`;
203
- this.tooltipHeaderDOM.style.width = `${contentsWidth}px`;
204
- this.tooltipHeaderDOM.style.height = 'auto';
205
- this.tooltipDOM.style.height = 'auto';
206
- this.tooltipBodyDOM.style.height = `${contentsHeight + 6}px`;
207
- this.tooltipDOM.style.display = 'block';
208
-
209
- // set tooltipDOM's positions
210
- const bodyWidth = document.body.clientWidth;
211
- const bodyHeight = document.body.clientHeight;
212
- const distanceMouseAndTooltip = 20;
213
- const tooltipDOMHeight = this.tooltipDOM?.offsetHeight
214
- || this.tooltipHeaderDOM?.offsetHeight + contentsHeight + BODY_PADDING;
215
- const maximumPosX = bodyWidth - contentsWidth - distanceMouseAndTooltip;
216
- const maximumPosY = bodyHeight - tooltipDOMHeight - distanceMouseAndTooltip;
217
- const expectedPosX = mouseX + distanceMouseAndTooltip;
218
- const expectedPosY = mouseY + distanceMouseAndTooltip;
219
- const reversedPosX = mouseX - contentsWidth - distanceMouseAndTooltip;
220
- const reversedPosY = mouseY - tooltipDOMHeight - distanceMouseAndTooltip;
221
- this.tooltipDOM.style.left = expectedPosX > maximumPosX
222
- ? `${reversedPosX}px`
223
- : `${expectedPosX}px`;
224
- this.tooltipDOM.style.top = expectedPosY > maximumPosY
225
- ? `${reversedPosY}px`
226
- : `${expectedPosY}px`;
227
- },
228
-
229
- /**
230
- * Draw series color shape
231
- * @param {object} context tooltip canvas context
232
- * @param {string} shape // 'circle' | 'rect' (default)
233
- * @param {object} centerPosition // {x: number, y: number}
234
- */
235
- drawSeriesColorShape(context, shape, centerPosition) {
236
- const fontSize = this.options.tooltip?.fontSize?.contents;
237
- const { x, y } = centerPosition;
238
-
239
- if (shape === 'circle') {
240
- context.beginPath();
241
- const circleSize = fontSize / 2;
242
- context.arc(x, y - (circleSize / 2), circleSize, 0, 2 * Math.PI);
243
- context.fill();
244
- } else {
245
- const rectSize = fontSize;
246
- context.fillRect(x - (rectSize / 3), y - (rectSize / 1.2), rectSize, rectSize);
247
- }
248
- },
249
-
250
- /**
251
- * Draw tooltip canvas
252
- * @param {object} hitInfo mousemove callback
253
- * @param {object} context tooltip canvas context
254
- *
255
- * @returns {undefined}
256
- */
257
- drawTooltip(hitInfo, context) {
258
- const ctx = context;
259
- const items = hitInfo.items;
260
- const [, maxValue] = hitInfo.maxTip;
261
- const seriesKeys = this.alignSeriesList(Object.keys(items));
262
- const boxPadding = this.getBoxPadding();
263
- const isHorizontal = this.options.horizontal;
264
- const opt = this.options.tooltip;
265
- const textHeight = this.getTextHeight();
266
- const seriesColorMarginRight = this.getColorMargin();
267
-
268
- // draw Tooltip header DOM
269
- if (this.axesX.length && this.axesY.length && opt.showHeader) {
270
- this.tooltipHeaderDOM.style.visibility = 'visible';
271
- } else {
272
- this.tooltipHeaderDOM.style.display = 'none';
273
- }
274
-
275
- // draw tooltip contents (series, value combination)
276
- let x = 2;
277
- let y = 2;
278
-
279
- x += Util.aliasPixel(x);
280
- y += Util.aliasPixel(y);
281
-
282
- ctx.save();
283
- ctx.scale(this.pixelRatio, this.pixelRatio);
284
-
285
- if (this.tooltipBodyDOM.style.overflowY === 'auto') {
286
- boxPadding.r += SCROLL_WIDTH;
287
- }
288
-
289
- x += boxPadding.l;
290
- y += boxPadding.t;
291
-
292
- ctx.font = this.getFontStyle('contents');
293
-
294
- const seriesList = [];
295
- seriesKeys.forEach((seriesName) => {
296
- seriesList.push({
297
- id: seriesName,
298
- data: items[seriesName].data,
299
- color: items[seriesName].color,
300
- name: items[seriesName].name,
301
- dataId: items[seriesName].id,
302
- });
303
- });
304
-
305
- if (opt.sortByValue) {
306
- seriesList.sort((a, b) => {
307
- let prev = a.data.o;
308
- let next = b.data.o;
309
-
310
- if (prev === null || prev === undefined) {
311
- prev = isHorizontal ? a.data.x : a.data.y;
312
- }
313
-
314
- if (next === null || next === undefined) {
315
- next = isHorizontal ? b.data.x : b.data.y;
316
- }
317
- return next - prev;
318
- });
319
- }
320
-
321
- this.setTooltipDOMStyle(opt);
322
-
323
- let textLineCnt = 1;
324
- for (let ix = 0; ix < seriesList.length; ix++) {
325
- const gdata = seriesList[ix].data;
326
- const color = seriesList[ix].color;
327
- const name = seriesList[ix].name;
328
- const valueText = gdata.formatted;
329
-
330
- let itemX = x + 4;
331
- let itemY = y + (textLineCnt * textHeight);
332
- itemX += Util.aliasPixel(itemX);
333
- itemY += Util.aliasPixel(itemY);
334
-
335
- ctx.beginPath();
336
-
337
- if (typeof color !== 'string') {
338
- ctx.fillStyle = Canvas.createGradient(
339
- ctx,
340
- isHorizontal,
341
- { x: itemX - 4, y: itemY, w: 12, h: -12 },
342
- color,
343
- );
344
- } else {
345
- ctx.fillStyle = color;
346
- }
347
-
348
- const curTooltipInfo = {
349
- id: seriesList[ix].id,
350
- name: seriesList[ix].name,
351
- value: valueText,
352
- dataId: seriesList[ix].dataId,
353
- };
354
-
355
- // 1. Draw series color
356
- this.drawSeriesColorShape(ctx, opt.colorShape, { x: itemX, y: itemY });
357
-
358
- // 2. Draw series name
359
- ctx.fillStyle = typeof opt.fontColor.label === 'function' ? opt.fontColor.label(curTooltipInfo) : opt.fontColor.label ?? opt.fontColor;
360
-
361
- const seriesNameSpaceWidth = opt.maxWidth - Math.round(ctx.measureText(maxValue).width)
362
- - boxPadding.l - boxPadding.r - seriesColorMarginRight - VALUE_MARGIN;
363
- const xPos = itemX + seriesColorMarginRight;
364
- const yPos = itemY;
365
-
366
- if (seriesNameSpaceWidth > ctx.measureText(name).width) { // draw normally
367
- ctx.fillText(name, xPos, yPos);
368
- } else if (opt.textOverflow === 'wrap') { // draw with wrap
369
- let line = '';
370
- let yPosWithWrap = yPos;
371
-
372
- for (let jx = 0; jx < name.length; jx++) {
373
- const char = name[jx];
374
- const temp = `${line}${char}`;
375
-
376
- if (ctx.measureText(temp).width > seriesNameSpaceWidth) {
377
- ctx.fillText(line, xPos, yPosWithWrap);
378
- line = char;
379
- textLineCnt += 1;
380
- yPosWithWrap += textHeight;
381
- } else {
382
- line = temp;
383
- }
384
- }
385
- ctx.fillText(line, xPos, yPosWithWrap);
386
- } else { // draw with ellipsis
387
- const shortSeriesName = Util.truncateLabelWithEllipsis(name, seriesNameSpaceWidth, ctx);
388
- ctx.fillText(shortSeriesName, xPos, yPos);
389
- }
390
-
391
- ctx.save();
392
-
393
- // 3. Draw value
394
- ctx.fillStyle = typeof opt.fontColor.value === 'function' ? opt.fontColor.value(curTooltipInfo) : opt.fontColor.value ?? opt.fontColor;
395
- ctx.textAlign = 'right';
396
- ctx.fillText(valueText, this.tooltipDOM.offsetWidth - boxPadding.r, itemY);
397
- ctx.restore();
398
- ctx.closePath();
399
-
400
- // 4. add lineSpacing
401
- y += LINE_SPACING;
402
- textLineCnt += 1;
403
- }
404
-
405
- ctx.restore();
406
- },
407
-
408
- /**
409
- * Draw tooltip canvas for heatmap
410
- * @param {object} hitInfo mousemove callback
411
- * @param {object} context tooltip canvas context
412
- *
413
- * @returns {undefined}
414
- */
415
- drawToolTipForHeatMap(hitInfo, context) {
416
- const ctx = context;
417
- const items = hitInfo.items;
418
- const sId = hitInfo.hitId;
419
- const hitItem = items[sId].data;
420
- const hitAxis = items[sId].axis;
421
- const hitColor = items[sId].color;
422
- const boxPadding = this.getBoxPadding();
423
- const isHorizontal = this.options.horizontal;
424
- const opt = this.options.tooltip;
425
- const series = Object.values(this.seriesList)[0];
426
- const textHeight = this.getTextHeight();
427
- const seriesColorMarginRight = this.getColorMargin();
428
-
429
- let isShow = false;
430
- let valueText = hitItem.formatted;
431
- const { colorState, isGradient } = series;
432
- if (isGradient) {
433
- const { min, max } = series.valueOpt;
434
- const ratio = convertToPercent(hitItem.o - min, max - min);
435
- const { start, end } = colorState[0];
436
- isShow = (start <= ratio && ratio <= end) || hitItem.o === -1;
437
- } else {
438
- const colorItem = colorState.find(({ id }) => id === hitItem.cId);
439
- isShow = colorItem?.show;
440
- valueText = colorItem?.label ?? valueText;
441
- }
442
-
443
- if (!isShow) {
444
- this.tooltipClear();
445
- return;
446
- }
447
-
448
- // draw Tooltip header DOM
449
- if (this.axesX.length && this.axesY.length && opt.showHeader) {
450
- this.tooltipHeaderDOM.style.visibility = 'visible';
451
- } else {
452
- this.tooltipHeaderDOM.style.display = 'none';
453
- }
454
-
455
- this.setTooltipDOMStyle(opt);
456
-
457
- // draw tooltip contents (series, value combination)
458
- ctx.save();
459
- ctx.scale(this.pixelRatio, this.pixelRatio);
460
-
461
- if (this.tooltipBodyDOM.style.overflowY === 'auto') {
462
- boxPadding.r += SCROLL_WIDTH;
463
- }
464
-
465
- const itemX = boxPadding.l + 2;
466
- const itemY = boxPadding.t + textHeight + 2;
467
-
468
- ctx.font = this.getFontStyle('contents');
469
-
470
- ctx.beginPath();
471
-
472
- if (typeof hitColor !== 'string') {
473
- ctx.fillStyle = Canvas.createGradient(
474
- ctx,
475
- isHorizontal,
476
- { x: itemX, y: itemY, w: 12, h: -12 },
477
- hitColor,
478
- );
479
- } else {
480
- ctx.fillStyle = hitColor;
481
- }
482
-
483
- const curTooltipInfo = {
484
- id: hitInfo.hitId,
485
- name: hitItem.y,
486
- value: valueText,
487
- dataId: items[sId].id,
488
- };
489
-
490
- // 1. Draw value color
491
- this.drawSeriesColorShape(ctx, opt.colorShape, { x: itemX, y: itemY });
492
-
493
- // 2. Draw value y names
494
- ctx.fillStyle = typeof opt.fontColor.label === 'function' ? opt.fontColor.label(curTooltipInfo) : opt.fontColor.label ?? opt.fontColor;
495
-
496
- if (this.axesY.length) {
497
- ctx.fillText(
498
- this.axesY[hitAxis.y].getLabelFormat(hitItem.y),
499
- itemX + seriesColorMarginRight, itemY,
500
- );
501
- }
502
-
503
- // 3. Draw value
504
- ctx.textAlign = 'right';
505
- ctx.fillStyle = typeof opt.fontColor.value === 'function' ? opt.fontColor.value(curTooltipInfo) : opt.fontColor.value ?? opt.fontColor;
506
- ctx.fillText(valueText, this.tooltipDOM.offsetWidth - boxPadding.r, itemY);
507
- ctx.closePath();
508
- },
509
-
510
- /**
511
- *
512
- * @param hitInfo
513
- * @param context
514
- */
515
- drawTooltipForScatter(hitInfo, context) {
516
- const ctx = context;
517
- const items = hitInfo.items;
518
- const [, maxValue] = hitInfo.maxTip;
519
- const seriesKeys = this.alignSeriesList(Object.keys(items));
520
- const boxPadding = this.getBoxPadding();
521
- const opt = this.options.tooltip;
522
- const textHeight = this.getTextHeight();
523
- const seriesColorMarginRight = this.getColorMargin();
524
-
525
- // draw Tooltip header DOM
526
- if (this.axesX.length && this.axesY.length && opt.showHeader) {
527
- this.tooltipHeaderDOM.style.visibility = 'visible';
528
- } else {
529
- this.tooltipHeaderDOM.style.display = 'none';
530
- }
531
-
532
- let x = 2;
533
- let y = 2;
534
-
535
- x += Util.aliasPixel(x);
536
- y += Util.aliasPixel(y);
537
-
538
- ctx.save();
539
- ctx.scale(this.pixelRatio, this.pixelRatio);
540
-
541
- if (this.tooltipBodyDOM.style.overflowY === 'auto') {
542
- boxPadding.r += SCROLL_WIDTH;
543
- }
544
-
545
- x += boxPadding.l;
546
- y += boxPadding.t;
547
-
548
- ctx.font = this.getFontStyle('contents');
549
-
550
- const seriesList = [];
551
- seriesKeys.forEach((seriesName) => {
552
- seriesList.push({
553
- data: items[seriesName].data,
554
- color: items[seriesName].color,
555
- name: items[seriesName].name,
556
- });
557
- });
558
-
559
- if (opt.sortByValue) {
560
- seriesList.sort((a, b) => {
561
- let prev = a.data.o;
562
- let next = b.data.o;
563
-
564
- if (prev === null || prev === undefined) {
565
- prev = a.data.y;
566
- }
567
-
568
- if (next === null || next === undefined) {
569
- next = b.data.y;
570
- }
571
-
572
- return next - prev;
573
- });
574
- }
575
-
576
- this.setTooltipDOMStyle(opt);
577
-
578
- let textLineCnt = 1;
579
- for (let ix = 0; ix < seriesList.length; ix++) {
580
- const gdata = seriesList[ix].data;
581
- const color = seriesList[ix].color;
582
- const name = seriesList[ix].name;
583
- const valueText = gdata.formatted;
584
-
585
- let itemX = x + 4;
586
- let itemY = y + (textLineCnt * textHeight);
587
- itemX += Util.aliasPixel(itemX);
588
- itemY += Util.aliasPixel(itemY);
589
-
590
- ctx.beginPath();
591
-
592
- if (typeof color !== 'string') {
593
- ctx.fillStyle = Canvas.createGradient(
594
- ctx,
595
- false,
596
- { x: itemX - 4, y: itemY, w: 12, h: -12 },
597
- color,
598
- );
599
- } else {
600
- ctx.fillStyle = color;
601
- }
602
-
603
- const curTooltipInfo = {
604
- id: hitInfo.hitId,
605
- name: seriesList[ix].name,
606
- value: valueText,
607
- dataId: seriesList[ix].dataId,
608
- };
609
-
610
- // 1. Draw series color
611
- this.drawSeriesColorShape(ctx, opt.colorShape, { x: itemX, y: itemY });
612
-
613
- // 2. Draw series name
614
- ctx.fillStyle = typeof opt.fontColor.label === 'function' ? opt.fontColor.label(curTooltipInfo) : opt.fontColor.label ?? opt.fontColor;
615
-
616
- const seriesNameSpaceWidth = opt.maxWidth - Math.round(ctx.measureText(maxValue).width)
617
- - boxPadding.l - boxPadding.r - seriesColorMarginRight - VALUE_MARGIN;
618
- const xPos = itemX + seriesColorMarginRight;
619
- const yPos = itemY;
620
-
621
- if (seriesNameSpaceWidth > ctx.measureText(name).width) { // draw normally
622
- ctx.fillText(name, xPos, yPos);
623
- } else if (opt.textOverflow === 'wrap') { // draw with wrap
624
- let line = '';
625
- let yPosWithWrap = yPos;
626
-
627
- for (let jx = 0; jx < name.length; jx++) {
628
- const char = name[jx];
629
- const temp = `${line}${char}`;
630
-
631
- if (ctx.measureText(temp).width > seriesNameSpaceWidth) {
632
- ctx.fillText(line, xPos, yPosWithWrap);
633
- line = char;
634
- textLineCnt += 1;
635
- yPosWithWrap += textHeight;
636
- } else {
637
- line = temp;
638
- }
639
- }
640
- ctx.fillText(line, xPos, yPosWithWrap);
641
- } else { // draw with ellipsis
642
- const shortSeriesName = Util.truncateLabelWithEllipsis(name, seriesNameSpaceWidth, ctx);
643
- ctx.fillText(shortSeriesName, xPos, yPos);
644
- }
645
-
646
- ctx.save();
647
-
648
- // 3. Draw value
649
- ctx.textAlign = 'right';
650
- ctx.fillStyle = typeof opt.fontColor.value === 'function' ? opt.fontColor.value(curTooltipInfo) : opt.fontColor.value ?? opt.fontColor;
651
- ctx.fillText(valueText, this.tooltipDOM.offsetWidth - boxPadding.r, itemY);
652
- ctx.restore();
653
- ctx.closePath();
654
-
655
- // 4. add lineSpacing
656
- y += LINE_SPACING;
657
- textLineCnt += 1;
658
- }
659
-
660
- ctx.restore();
661
- },
662
-
663
- setCustomTooltipLayoutPosition(hitInfo, e) {
664
- const mouseX = e.pageX;
665
- const mouseY = e.pageY;
666
-
667
- const customTooltipEl = this.tooltipDOM.getElementsByClassName('ev-chart-tooltip-custom')?.[0];
668
- if (!customTooltipEl && !this.tooltipDOM) {
669
- return;
670
- }
671
-
672
- this.tooltipDOM.style.display = 'block';
673
- const contentsWidth = customTooltipEl.offsetWidth;
674
- const contentsHeight = customTooltipEl.offsetHeight;
675
-
676
- this.tooltipDOM.style.height = 'auto';
677
- this.tooltipBodyDOM.style.height = `${contentsHeight + 6}px`;
678
-
679
- const bodyWidth = document.body.clientWidth;
680
- const bodyHeight = document.body.clientHeight;
681
- const tooltipDOMSize = this.tooltipDOM?.getBoundingClientRect();
682
- const distanceMouseAndTooltip = 20;
683
- const maximumPosX = bodyWidth - contentsWidth - distanceMouseAndTooltip;
684
- const maximumPosY = bodyHeight - tooltipDOMSize?.height - distanceMouseAndTooltip;
685
- const expectedPosX = mouseX + distanceMouseAndTooltip;
686
- const expectedPosY = mouseY + distanceMouseAndTooltip;
687
- const reversedPosX = mouseX - contentsWidth - distanceMouseAndTooltip;
688
- const reversedPosY = mouseY - tooltipDOMSize?.height - distanceMouseAndTooltip;
689
- this.tooltipDOM.style.left = expectedPosX > maximumPosX
690
- ? `${reversedPosX}px`
691
- : `${expectedPosX}px`;
692
- this.tooltipDOM.style.top = expectedPosY > maximumPosY
693
- ? `${reversedPosY}px`
694
- : `${expectedPosY}px`;
695
- },
696
-
697
- /**
698
- * Draw User Custom Tooltip (tooltip > formatter > html)
699
- * call "formatter > html" and append to tooltip DOM
700
- * @param hitInfoItems
701
- */
702
- drawCustomTooltip(hitInfoItems) {
703
- const opt = this.options?.tooltip;
704
- if (opt.formatter?.html) {
705
- this.tooltipDOM.innerHTML = '';
706
-
707
- const seriesList = [];
708
- Object.keys(hitInfoItems).forEach((sId) => {
709
- seriesList.push({
710
- sId,
711
- data: hitInfoItems[sId].data,
712
- color: hitInfoItems[sId].color,
713
- name: hitInfoItems[sId].name,
714
- dataId: hitInfoItems[sId].id,
715
- index: hitInfoItems[sId].index,
716
- });
717
- });
718
-
719
- const userCustomTooltipBody = Util.htmlToElement(opt?.formatter?.html((seriesList)));
720
- if (userCustomTooltipBody) {
721
- this.tooltipDOM.appendChild(userCustomTooltipBody);
722
- }
723
-
724
- this.tooltipDOM.style.overflowY = 'hidden';
725
- this.tooltipDOM.style.backgroundColor = opt.backgroundColor;
726
- this.tooltipDOM.style.border = `1px solid ${opt.borderColor}`;
727
- this.tooltipDOM.style.color = opt.fontColor?.title ?? opt.fontColor;
728
- }
729
- },
730
-
731
- /**
732
- * set style properties on tooltip DOM
733
- * @param tooltipOptions
734
- */
735
- setTooltipDOMStyle(tooltipOptions) {
736
- this.tooltipDOM.style.overflowY = 'hidden';
737
- this.tooltipDOM.style.backgroundColor = tooltipOptions.backgroundColor;
738
- this.tooltipDOM.style.border = `1px solid ${tooltipOptions.borderColor}`;
739
- this.tooltipDOM.style.color = tooltipOptions.fontColor?.title ?? tooltipOptions.fontColor;
740
-
741
- this.tooltipHeaderDOM.style.fontSize = `${tooltipOptions.fontSize.title}px`;
742
- this.tooltipHeaderDOM.style.fontFamily = this.getFontStyle('title');
743
-
744
- if (tooltipOptions.useShadow) {
745
- const shadowColor = `rgba(0, 0, 0, ${tooltipOptions.shadowOpacity})`;
746
- this.tooltipDOM.style.boxShadow = `2px 2px 2px ${shadowColor}`;
747
- }
748
-
749
- this.tooltipDOM.style.display = 'block';
750
- },
751
-
752
- /**
753
- * Draw graph item highlight
754
- * @param {object} hitInfo mousemove callback
755
- * @param {object} ctx overlayCanvas context
756
- *
757
- * @returns {undefined}
758
- */
759
- drawItemsHighlight(hitInfo, ctx) {
760
- Object.keys(hitInfo.items).forEach((sId) => {
761
- const series = this.seriesList[sId];
762
- series.itemHighlight(hitInfo.items[sId], ctx, hitInfo.items[sId].index);
763
-
764
- if (Util.isDoughnutHole(series.type)) {
765
- this.drawDoughnutHole(ctx);
766
- }
767
- });
768
- },
769
-
770
- /**
771
- * Draw chart indicator with mousemove
772
- * @param {object} offset mousemove callback
773
- * @param {string} color indicator color
774
- *
775
- * @returns {undefined}
776
- */
777
- drawIndicator(offset, color) {
778
- const ctx = this.overlayCtx;
779
- const [offsetX, offsetY] = offset;
780
- const graphPos = {
781
- x1: this.chartRect.x1 + this.labelOffset.left,
782
- x2: this.chartRect.x2 - this.labelOffset.right,
783
- y1: this.chartRect.y1 + this.labelOffset.top,
784
- y2: this.chartRect.y2 - this.labelOffset.bottom,
785
- };
786
- const mouseXIp = 15; // mouseInterpolation - 더 넓은 범위에서 감지
787
- const mouseYIp = 15; // Y축도 동일하게 증가
788
- const options = this.options;
789
-
790
- if (offsetX >= (graphPos.x1 - mouseXIp) && offsetX <= (graphPos.x2 + mouseXIp)
791
- && offsetY >= (graphPos.y1 - mouseYIp) && offsetY <= (graphPos.y2 + mouseYIp)) {
792
- ctx.beginPath();
793
- ctx.save();
794
- ctx.strokeStyle = color;
795
- ctx.lineWidth = 1;
796
-
797
- if (options.indicator?.segments) {
798
- ctx.setLineDash(options.indicator.segments);
799
- }
800
-
801
- if (options.horizontal) {
802
- ctx.moveTo(graphPos.x1, offsetY + 0.5);
803
- ctx.lineTo(graphPos.x2, offsetY + 0.5);
804
- } else {
805
- ctx.moveTo(offsetX + 0.5, graphPos.y1);
806
- ctx.lineTo(offsetX + 0.5, graphPos.y2);
807
- }
808
-
809
- ctx.stroke();
810
- ctx.restore();
811
- ctx.closePath();
812
- }
813
- },
814
- /**
815
- * Get hovered axis label with mousemove
816
- * @param {object} offset mousemove callback
817
- *
818
- * @returns {number | null} hovered axis label
819
- */
820
- getTimeLabel(offset) {
821
- const options = this.options;
822
-
823
- if (
824
- options.syncHover === false
825
- || (!options.horizontal && !options.axesX.every(({ type }) => type === 'time'))
826
- || (options.horizontal && !options.axesY.every(({ type }) => type === 'time'))) {
827
- return null;
828
- }
829
-
830
- const fromTime = +this.data.labels?.[0];
831
- const toTime = +this.data.labels?.[this.data.labels.length - 1];
832
- if (fromTime == null || toTime == null) {
833
- return null;
834
- }
835
-
836
- const [offsetX, offsetY] = offset;
837
- const graphPos = {
838
- x1: this.chartRect.x1 + this.labelOffset.left,
839
- x2: this.chartRect.x2 - this.labelOffset.right,
840
- y1: this.chartRect.y1 + this.labelOffset.top,
841
- y2: this.chartRect.y2 - this.labelOffset.bottom,
842
- };
843
-
844
- if (options.horizontal) {
845
- const chartHeight = graphPos.y2 - graphPos.y1;
846
- const hoverYAxis = offsetY - graphPos.y1;
847
- const hoverTime = ((hoverYAxis * (toTime - fromTime)) / chartHeight) + fromTime;
848
- return Math.round(hoverTime);
849
- }
850
- const chartWidth = graphPos.x2 - graphPos.x1;
851
- const hoverXAxis = offsetX - graphPos.x1;
852
- const hoverTime = ((hoverXAxis * (toTime - fromTime)) / chartWidth) + fromTime;
853
- return Math.round(hoverTime);
854
- },
855
- /**
856
- * Draw chart indicator with other grouped chart's mousemove
857
- * @param {object} hoveredLabel chart direction and hovered axis label
858
- *
859
- * @returns {undefined}
860
- */
861
- drawSyncedIndicator({ horizontal, label, mousePosition, dataLabel }) {
862
- if (!this._canDrawSyncedIndicator(horizontal, mousePosition)) {
863
- return;
864
- }
865
-
866
- if (dataLabel) {
867
- this.drawSyncedIndicatorForTooltip({ dataLabel, mousePosition });
868
- return;
869
- }
870
-
871
- const fromTime = +this.data.labels?.[0];
872
- const toTime = +this.data.labels?.[this.data.labels.length - 1];
873
- const [clientX, clientY] = mousePosition;
874
- const { top, bottom, left, right } = this.chartDOM.getBoundingClientRect();
875
-
876
- const isHoveredChart = inRange(clientX, left, right) && inRange(clientY, bottom, top);
877
- if (isHoveredChart) {
878
- return;
879
- }
880
-
881
- this.overlayClear();
882
- const graphPos = {
883
- x1: this.chartRect.x1 + this.labelOffset.left,
884
- x2: this.chartRect.x2 - this.labelOffset.right,
885
- y1: this.chartRect.y1 + this.labelOffset.top,
886
- y2: this.chartRect.y2 - this.labelOffset.bottom,
887
- };
888
-
889
- if (horizontal) {
890
- const chartHeight = graphPos.y2 - graphPos.y1;
891
- const offsetY = (chartHeight * (label - fromTime)) / (toTime - fromTime) + graphPos.y1;
892
- this.drawIndicator([graphPos.x2, offsetY], this.options.indicator.color);
893
- } else {
894
- const chartWidth = graphPos.x2 - graphPos.x1;
895
- const offsetX = (chartWidth * (label - fromTime)) / (toTime - fromTime) + graphPos.x1;
896
- this.drawIndicator([offsetX, graphPos.y2], this.options.indicator.color);
897
- }
898
- },
899
-
900
- _canDrawSyncedIndicator(horizontal, mousePosition) {
901
- if (!mousePosition || !!horizontal !== !!this.options.horizontal) {
902
- return false;
903
- }
904
-
905
- return this._isTimeBasedSyncEnabled(horizontal) && this._hasValidTimeRange();
906
- },
907
-
908
- _isTimeBasedSyncEnabled(horizontal) {
909
- if (this.options.syncHover === false) return false;
910
- if (!this.data?.labels?.length) return false;
911
-
912
- const timeAxes = horizontal
913
- ? this.options.axesY.every(({ type }) => type === 'time')
914
- : this.options.axesX.every(({ type }) => type === 'time');
915
-
916
- return timeAxes;
917
- },
918
-
919
- _hasValidTimeRange() {
920
- const fromTime = +this.data.labels?.[0];
921
- const toTime = +this.data.labels?.[this.data.labels.length - 1];
922
- return fromTime != null && toTime != null;
923
- },
924
-
925
- /**
926
- * 제공된 dataLabel과 일치하는 Label이 있다면 indicator를 그림
927
- * @param {object} dataLabel data label
928
- * @param {object} mousePosition mouse position
929
- *
930
- * @returns {undefined}
931
- */
932
- drawSyncedIndicatorForTooltip({ dataLabel, mousePosition }) {
933
- if (!this.data?.labels || !dataLabel) {
934
- return;
935
- }
936
-
937
- const matchingLabelIndex = this.data.labels.findIndex(
938
- label => label?.valueOf() === dataLabel?.valueOf(),
939
- );
940
- if (matchingLabelIndex === -1) {
941
- this.overlayClear();
942
- return;
943
- }
944
-
945
- const { horizontal } = this.options;
946
- const { top, bottom, left, right } = this.chartDOM.getBoundingClientRect();
947
- const isHoveredChart = inRange(mousePosition[0], left, right)
948
- && inRange(mousePosition[1], bottom, top);
949
- if (isHoveredChart) {
950
- return;
951
- }
952
-
953
- this.overlayClear();
954
-
955
- const graphPos = {
956
- x1: this.chartRect.x1 + this.labelOffset.left,
957
- x2: this.chartRect.x2 - this.labelOffset.right,
958
- y1: this.chartRect.y1 + this.labelOffset.top,
959
- y2: this.chartRect.y2 - this.labelOffset.bottom,
960
- };
961
-
962
- const labelsCount = this.data.labels.length;
963
- let indicatorPosition;
964
-
965
- if (horizontal) {
966
- const chartHeight = graphPos.y2 - graphPos.y1;
967
- // CategoryMode인 경우 라벨들이 균등 간격으로 배치됨
968
- const isCategoryMode = this.options.axesY?.some(axis => axis.categoryMode);
969
- const positionY = isCategoryMode
970
- ? graphPos.y1 + (chartHeight * (matchingLabelIndex + 0.5)) / labelsCount
971
- : graphPos.y1 + (chartHeight * matchingLabelIndex) / (labelsCount - 1);
972
- indicatorPosition = [graphPos.x2, positionY];
973
- } else {
974
- const chartWidth = graphPos.x2 - graphPos.x1;
975
- // CategoryMode인 경우 라벨들이 균등 간격으로 배치됨
976
- const isCategoryMode = this.options.axesX?.some(axis => axis.categoryMode);
977
- const positionX = isCategoryMode
978
- ? graphPos.x1 + (chartWidth * (matchingLabelIndex + 0.5)) / labelsCount
979
- : graphPos.x1 + (chartWidth * matchingLabelIndex) / (labelsCount - 1);
980
- indicatorPosition = [positionX, graphPos.y2];
981
- }
982
-
983
- this.drawIndicator(indicatorPosition, this.options.indicator.color);
984
- },
985
-
986
- /**
987
- * Clear tooltip canvas
988
- *
989
- * @returns {undefined}
990
- */
991
- tooltipClear() {
992
- this.clearRectRatio = (this.pixelRatio < 1) ? this.pixelRatio : 1;
993
-
994
- this.tooltipCtx.clearRect(0, 0, this.tooltipCanvas.width / this.clearRectRatio,
995
- this.tooltipCanvas.height / this.clearRectRatio);
996
-
997
- this.tooltipDOM.style.display = 'none';
998
- },
999
-
1000
- /**
1001
- * Order series list by groups
1002
- * @param {array} sKeys series list that is hit by mouse cursor. (not all of series)
1003
- *
1004
- * @returns {array} ordered series list by groups
1005
- */
1006
- alignSeriesList(sKeys) {
1007
- const groups = this.data.groups;
1008
- const seriesList = this.seriesList;
1009
- const result = [];
1010
-
1011
- groups.forEach((group) => {
1012
- group.slice().reverse().forEach((sId) => {
1013
- const series = seriesList[sId];
1014
-
1015
- if (series && series.showLegend && sKeys.includes(sId)) {
1016
- result.push(sId);
1017
- }
1018
- });
1019
- });
1020
-
1021
- Object.keys(seriesList).forEach((sId) => {
1022
- const series = seriesList[sId];
1023
-
1024
- if (!series.isExistGrp && series.showLegend && sKeys.includes(sId)) {
1025
- result.push(sId);
1026
- }
1027
- });
1028
-
1029
- return result;
1030
- },
1031
-
1032
- tooltipDestroy() {
1033
- if (this.tooltipDOM) {
1034
- this.tooltipDOM.remove();
1035
- this.tooltipDOM = null;
1036
- }
1037
- this.isInitTooltip = false;
1038
- },
1039
- };
1040
-
1041
- export default modules;