evui 3.3.12 → 3.3.15
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.
- package/dist/evui.common.js +1489 -716
- package/dist/evui.common.js.map +1 -1
- package/dist/evui.umd.js +1489 -716
- package/dist/evui.umd.js.map +1 -1
- package/dist/evui.umd.min.js +1 -1
- package/dist/evui.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/chart/Chart.vue +23 -3
- package/src/components/chart/chart.core.js +12 -9
- package/src/components/chart/element/element.heatmap.js +293 -51
- package/src/components/chart/element/element.line.js +39 -42
- package/src/components/chart/element/element.pie.js +17 -17
- package/src/components/chart/element/element.tip.js +1 -1
- package/src/components/chart/helpers/helpers.constant.js +13 -11
- package/src/components/chart/model/model.series.js +1 -1
- package/src/components/chart/model/model.store.js +121 -73
- package/src/components/chart/plugins/plugins.interaction.js +111 -25
- package/src/components/chart/plugins/plugins.legend.js +28 -7
- package/src/components/chart/plugins/plugins.pie.js +17 -0
- package/src/components/chart/plugins/plugins.tooltip.js +28 -14
- package/src/components/chart/scale/scale.js +13 -3
- package/src/components/chart/scale/scale.step.js +52 -10
- package/src/components/chart/scale/scale.time.category.js +27 -3
- package/src/components/chart/uses.js +23 -1
- package/src/components/grid/Grid.vue +26 -11
- package/src/components/grid/grid.summary.vue +36 -6
- package/src/components/grid/uses.js +4 -1
- package/src/components/treeGrid/TreeGrid.vue +29 -11
- package/src/components/treeGrid/uses.js +4 -1
|
@@ -102,7 +102,8 @@ class Line {
|
|
|
102
102
|
const getXPos = val => Canvas.calculateX(val, minmaxX.graphMin, minmaxX.graphMax, xArea, xsp);
|
|
103
103
|
const getYPos = val => Canvas.calculateY(val, minmaxY.graphMin, minmaxY.graphMax, yArea, ysp);
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
// draw line
|
|
106
|
+
this.data.reduce((prev, curr, ix) => {
|
|
106
107
|
x = getXPos(curr.x);
|
|
107
108
|
y = getYPos(curr.y);
|
|
108
109
|
|
|
@@ -110,22 +111,12 @@ class Line {
|
|
|
110
111
|
x += Util.aliasPixel(x);
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (this.fill && prev.y !== null && !this.stackIndex) {
|
|
117
|
-
ctx.stroke();
|
|
118
|
-
ctx.lineTo(prev.xp, endPoint);
|
|
119
|
-
ctx.lineTo(item[startFillIndex].xp, endPoint);
|
|
120
|
-
|
|
121
|
-
ctx.fill();
|
|
122
|
-
ctx.beginPath();
|
|
123
|
-
}
|
|
124
|
-
}
|
|
114
|
+
if (ix === 0) {
|
|
115
|
+
ctx.moveTo(x, y);
|
|
116
|
+
}
|
|
125
117
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|| prev.x === null || curr.x === null) {
|
|
118
|
+
const isNullValue = prev.y === null || curr.y === null || prev.x === null || curr.x === null;
|
|
119
|
+
if (isNullValue) {
|
|
129
120
|
ctx.moveTo(x, y);
|
|
130
121
|
} else {
|
|
131
122
|
ctx.lineTo(x, y);
|
|
@@ -139,39 +130,45 @@ class Line {
|
|
|
139
130
|
|
|
140
131
|
ctx.stroke();
|
|
141
132
|
|
|
142
|
-
|
|
133
|
+
// draw fill
|
|
134
|
+
if (this.fill && this.data.length) {
|
|
135
|
+
ctx.beginPath();
|
|
143
136
|
|
|
144
|
-
if (this.fill && dataLen) {
|
|
145
137
|
ctx.fillStyle = Util.colorStringToRgba(mainColor, fillOpacity);
|
|
146
138
|
|
|
147
|
-
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
ctx.lineTo(x, y);
|
|
160
|
-
|
|
161
|
-
if (ix === reversedDataList.length - 1) {
|
|
162
|
-
ctx.lineTo(x, getYPos(curr.b + curr.o));
|
|
163
|
-
}
|
|
164
|
-
} else if (prev && prev.o) {
|
|
165
|
-
ctx.lineTo(getXPos(prev.x), getYPos(prev.b + prev.o));
|
|
139
|
+
this.data.forEach((currData, ix) => {
|
|
140
|
+
const isEmptyPoint = data => data?.x === null || data?.y === null
|
|
141
|
+
|| data?.x === undefined || data?.y === undefined;
|
|
142
|
+
|
|
143
|
+
const nextData = this.data[ix + 1];
|
|
144
|
+
|
|
145
|
+
if (isEmptyPoint(currData)) {
|
|
146
|
+
startFillIndex = ix + 1;
|
|
147
|
+
|
|
148
|
+
if (!isEmptyPoint(nextData)) {
|
|
149
|
+
ctx.moveTo(nextData.xp, nextData.yp);
|
|
166
150
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
151
|
+
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
ctx.lineTo(currData.xp, currData.yp);
|
|
156
|
+
|
|
157
|
+
if (isEmptyPoint(nextData)) {
|
|
158
|
+
for (let jx = ix; jx >= startFillIndex; jx--) {
|
|
159
|
+
const prevData = this.data[jx];
|
|
160
|
+
const xp = prevData.xp;
|
|
161
|
+
const bp = getYPos(prevData.b) ?? endPoint;
|
|
162
|
+
ctx.lineTo(xp, bp);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
ctx.closePath();
|
|
166
|
+
}
|
|
167
|
+
});
|
|
172
168
|
|
|
173
169
|
ctx.fill();
|
|
174
170
|
}
|
|
171
|
+
|
|
175
172
|
if (this.point || isExistSelectedLabel) {
|
|
176
173
|
ctx.strokeStyle = Util.colorStringToRgba(mainColor, mainColorOpacity);
|
|
177
174
|
const focusStyle = Util.colorStringToRgba(pointFillColor, 1);
|
|
@@ -45,7 +45,6 @@ class Pie {
|
|
|
45
45
|
const slice = new Path2D();
|
|
46
46
|
|
|
47
47
|
const radius = this.isSelect ? this.radius + 5 : this.radius;
|
|
48
|
-
const doughnutHoleRadius = this.radius * this.doughnutHoleSize;
|
|
49
48
|
|
|
50
49
|
const color = this.color;
|
|
51
50
|
const noneDownplayOpacity = color.includes('rgba') ? Util.getOpacity(color) : 1;
|
|
@@ -66,7 +65,7 @@ class Pie {
|
|
|
66
65
|
}
|
|
67
66
|
|
|
68
67
|
if (this.showValue?.use) {
|
|
69
|
-
this.drawValueLabels(ctx
|
|
68
|
+
this.drawValueLabels(ctx);
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
ctx.closePath();
|
|
@@ -115,7 +114,6 @@ class Pie {
|
|
|
115
114
|
itemHighlight(item, context) {
|
|
116
115
|
const ctx = context;
|
|
117
116
|
const radius = this.isSelect ? this.radius + 5 : this.radius;
|
|
118
|
-
const doughnutHoleRadius = this.radius * this.doughnutHoleSize;
|
|
119
117
|
|
|
120
118
|
ctx.save();
|
|
121
119
|
ctx.shadowOffsetX = 0;
|
|
@@ -133,7 +131,7 @@ class Pie {
|
|
|
133
131
|
ctx.fill();
|
|
134
132
|
|
|
135
133
|
if (this.showValue?.use) {
|
|
136
|
-
this.drawValueLabels(ctx
|
|
134
|
+
this.drawValueLabels(ctx);
|
|
137
135
|
}
|
|
138
136
|
|
|
139
137
|
ctx.closePath();
|
|
@@ -146,19 +144,9 @@ class Pie {
|
|
|
146
144
|
* @param context canvas context
|
|
147
145
|
*/
|
|
148
146
|
drawValueLabels(context) {
|
|
149
|
-
const { fontSize, textColor, formatter } = this.showValue;
|
|
150
147
|
const ctx = context;
|
|
151
|
-
|
|
152
|
-
ctx.save();
|
|
153
|
-
ctx.beginPath();
|
|
154
|
-
|
|
155
|
-
ctx.font = `normal normal normal ${fontSize}px Roboto`;
|
|
156
|
-
ctx.fillStyle = textColor;
|
|
157
|
-
ctx.lineWidth = 1;
|
|
158
|
-
ctx.textAlign = 'center';
|
|
159
|
-
ctx.textBaseline = 'middle';
|
|
160
|
-
|
|
161
148
|
const value = this.data.o;
|
|
149
|
+
const { fontSize, textColor, formatter } = this.showValue;
|
|
162
150
|
|
|
163
151
|
let formattedTxt;
|
|
164
152
|
if (formatter) {
|
|
@@ -180,15 +168,27 @@ class Pie {
|
|
|
180
168
|
&& radius >= valueWidth * ratio
|
|
181
169
|
&& radius >= valueHeight * ratio
|
|
182
170
|
) {
|
|
171
|
+
ctx.save();
|
|
172
|
+
ctx.beginPath();
|
|
173
|
+
|
|
174
|
+
const noneDownplayOpacity = textColor.includes('rgba') ? Util.getOpacity(textColor) : 1;
|
|
175
|
+
const opacity = this.state === 'downplay' ? 0.1 : noneDownplayOpacity;
|
|
176
|
+
|
|
177
|
+
ctx.font = `normal normal normal ${fontSize}px Roboto`;
|
|
178
|
+
ctx.fillStyle = Util.colorStringToRgba(textColor, opacity);
|
|
179
|
+
ctx.lineWidth = 1;
|
|
180
|
+
ctx.textAlign = 'center';
|
|
181
|
+
ctx.textBaseline = 'middle';
|
|
182
|
+
|
|
183
183
|
const halfRadius = (radius / 2) + this.doughnutHoleSize;
|
|
184
184
|
const centerAngle = ((this.endAngle - this.startAngle) / 2) + this.startAngle;
|
|
185
185
|
const xPos = halfRadius * Math.cos(centerAngle) + this.centerX;
|
|
186
186
|
const yPos = halfRadius * Math.sin(centerAngle) + this.centerY;
|
|
187
187
|
|
|
188
188
|
ctx.fillText(formattedTxt, xPos, yPos);
|
|
189
|
-
}
|
|
190
189
|
|
|
191
|
-
|
|
190
|
+
ctx.restore();
|
|
191
|
+
}
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
|
|
@@ -250,7 +250,7 @@ const modules = {
|
|
|
250
250
|
const opt = this.options;
|
|
251
251
|
const isHorizontal = !!opt.horizontal;
|
|
252
252
|
const labelTipOpt = opt.selectLabel;
|
|
253
|
-
const { dataIndex, data, label } = this.
|
|
253
|
+
const { dataIndex, data, label } = this.defaultSelectInfo;
|
|
254
254
|
let drawTip = false;
|
|
255
255
|
|
|
256
256
|
if (dataIndex.length) {
|
|
@@ -129,17 +129,19 @@ export const PLOT_BAND_OPTION = {
|
|
|
129
129
|
};
|
|
130
130
|
|
|
131
131
|
export const HEAT_MAP_OPTION = {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
132
|
+
show: true,
|
|
133
|
+
highlight: {
|
|
134
|
+
maxShadowOpacity: 0.4,
|
|
135
|
+
},
|
|
136
|
+
xAxisIndex: 0,
|
|
137
|
+
yAxisIndex: 0,
|
|
138
|
+
showLegend: true,
|
|
139
|
+
showValue: {
|
|
140
|
+
use: false,
|
|
141
|
+
fontSize: 12,
|
|
142
|
+
textColor: '#000000',
|
|
143
|
+
formatter: null,
|
|
144
|
+
decimalPoint: 0,
|
|
143
145
|
},
|
|
144
146
|
};
|
|
145
147
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { reverse } from 'lodash-es';
|
|
2
2
|
import Util from '../helpers/helpers.util';
|
|
3
|
-
import { TIME_INTERVALS } from '../helpers/helpers.constant';
|
|
4
3
|
|
|
5
4
|
const modules = {
|
|
6
5
|
/**
|
|
@@ -37,8 +36,9 @@ const modules = {
|
|
|
37
36
|
const sData = data[seriesID];
|
|
38
37
|
|
|
39
38
|
if (series && sData) {
|
|
39
|
+
series.labels = label;
|
|
40
40
|
series.data = this.addSeriesDSForHeatMap(sData);
|
|
41
|
-
series.minMax = this.
|
|
41
|
+
series.minMax = this.getSeriesMinMax(series.data);
|
|
42
42
|
series.valueOpt = this.getSeriesValueOptForHeatMap(series);
|
|
43
43
|
}
|
|
44
44
|
});
|
|
@@ -301,17 +301,20 @@ const modules = {
|
|
|
301
301
|
/**
|
|
302
302
|
* Take data to create data for each series
|
|
303
303
|
* @param {array} data data array for each series
|
|
304
|
+
* @param {object} label chart label
|
|
305
|
+
*
|
|
304
306
|
* @returns {array} data info added position and etc
|
|
305
307
|
*/
|
|
306
308
|
addSeriesDSForHeatMap(data) {
|
|
307
|
-
return data.map(
|
|
308
|
-
x
|
|
309
|
-
y
|
|
310
|
-
o:
|
|
309
|
+
return data.map(({ x, y, value }) => ({
|
|
310
|
+
x,
|
|
311
|
+
y,
|
|
312
|
+
o: value,
|
|
311
313
|
xp: null,
|
|
312
314
|
yp: null,
|
|
315
|
+
w: null,
|
|
316
|
+
h: null,
|
|
313
317
|
dataColor: null,
|
|
314
|
-
value: item.value,
|
|
315
318
|
cId: null,
|
|
316
319
|
}));
|
|
317
320
|
},
|
|
@@ -414,92 +417,42 @@ const modules = {
|
|
|
414
417
|
return def;
|
|
415
418
|
},
|
|
416
419
|
|
|
417
|
-
adjustMinMax(max, min, opt, space) {
|
|
418
|
-
if ((opt.type === 'time' && opt.categoryMode) || opt.type === 'step') {
|
|
419
|
-
return {
|
|
420
|
-
max,
|
|
421
|
-
min,
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
let targetMax = max;
|
|
426
|
-
let targetMin = min;
|
|
427
|
-
if (targetMax > 0 && opt.interval && space) {
|
|
428
|
-
if (targetMax < (opt.interval * space)) {
|
|
429
|
-
targetMax += opt.interval;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
let targetInterval = opt.interval;
|
|
434
|
-
if (opt.type === 'time') {
|
|
435
|
-
if (typeof targetInterval === 'string') {
|
|
436
|
-
targetInterval = TIME_INTERVALS[targetInterval].size;
|
|
437
|
-
} else if (typeof targetInterval === 'object') {
|
|
438
|
-
targetInterval = targetInterval.time * TIME_INTERVALS[targetInterval.unit].size;
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
if (!opt.startToZero || targetMin > 0) {
|
|
443
|
-
const targetSpace = space ? (space - 1) : (targetMax - targetMin);
|
|
444
|
-
const targetStep = Math.ceil((max - targetMin) / targetSpace);
|
|
445
|
-
targetMin = targetMin < targetStep ? 0 : targetMin - targetStep;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
return {
|
|
449
|
-
max: targetMax,
|
|
450
|
-
min: targetMin,
|
|
451
|
-
};
|
|
452
|
-
},
|
|
453
|
-
/**
|
|
454
|
-
* Take series data to create min/max info for each series
|
|
455
|
-
* @param data
|
|
456
|
-
* @param spaces
|
|
457
|
-
* @returns {*|{maxDomain: null, minY: null, minX: null, maxY: null, maxX: null}}
|
|
458
|
-
*/
|
|
459
|
-
getSeriesMinMaxForHeatMap(data, spaces) {
|
|
460
|
-
const axesXOption = this.options.axesX[0];
|
|
461
|
-
const axesYOption = this.options.axesY[0];
|
|
462
|
-
const seriesMinMax = this.getSeriesMinMax(data);
|
|
463
|
-
|
|
464
|
-
const adjustX = this.adjustMinMax(seriesMinMax.maxX, seriesMinMax.minX, axesXOption, spaces.x);
|
|
465
|
-
seriesMinMax.maxX = adjustX.max;
|
|
466
|
-
seriesMinMax.minX = adjustX.min;
|
|
467
|
-
|
|
468
|
-
const adjustY = this.adjustMinMax(seriesMinMax.maxY, seriesMinMax.minY, axesYOption, spaces.y);
|
|
469
|
-
seriesMinMax.maxY = adjustY.max;
|
|
470
|
-
seriesMinMax.minY = adjustY.min;
|
|
471
|
-
|
|
472
|
-
return seriesMinMax;
|
|
473
|
-
},
|
|
474
|
-
|
|
475
420
|
getSeriesValueOptForHeatMap(series) {
|
|
476
421
|
const data = series.data;
|
|
477
|
-
const colorOpt =
|
|
478
|
-
const colorAxis = series.colorAxis;
|
|
422
|
+
const colorOpt = this.options.heatMapColor;
|
|
479
423
|
const categoryCnt = colorOpt.categoryCnt;
|
|
480
424
|
|
|
425
|
+
let minValue;
|
|
481
426
|
let maxValue = 0;
|
|
427
|
+
|
|
482
428
|
let isExistError = false;
|
|
483
|
-
data.forEach(({ value }) => {
|
|
429
|
+
data.forEach(({ o: value }) => {
|
|
484
430
|
if (maxValue < value) {
|
|
485
|
-
maxValue = value;
|
|
431
|
+
maxValue = Math.max(maxValue, value);
|
|
486
432
|
}
|
|
433
|
+
|
|
487
434
|
if (value < 0) {
|
|
488
435
|
isExistError = true;
|
|
436
|
+
} else if (minValue === undefined) {
|
|
437
|
+
minValue = value;
|
|
438
|
+
} else {
|
|
439
|
+
minValue = Math.min(minValue, value);
|
|
489
440
|
}
|
|
490
441
|
});
|
|
491
|
-
|
|
492
|
-
if (isExistError && colorAxis.length === categoryCnt) {
|
|
493
|
-
colorAxis.push({
|
|
442
|
+
|
|
443
|
+
if (isExistError && series.colorAxis.length === categoryCnt) {
|
|
444
|
+
series.colorAxis.push({
|
|
494
445
|
id: `color#${categoryCnt}`,
|
|
495
446
|
value: colorOpt.error,
|
|
496
447
|
state: 'normal',
|
|
497
448
|
show: true,
|
|
498
449
|
});
|
|
499
450
|
}
|
|
451
|
+
|
|
500
452
|
return {
|
|
453
|
+
min: minValue,
|
|
501
454
|
max: maxValue,
|
|
502
|
-
interval:
|
|
455
|
+
interval: Math.ceil((maxValue - minValue) / categoryCnt),
|
|
503
456
|
existError: isExistError,
|
|
504
457
|
};
|
|
505
458
|
},
|
|
@@ -673,6 +626,101 @@ const modules = {
|
|
|
673
626
|
};
|
|
674
627
|
},
|
|
675
628
|
|
|
629
|
+
/**
|
|
630
|
+
* Find seriesId by position x and y
|
|
631
|
+
* @param {array} offset position x and y
|
|
632
|
+
*
|
|
633
|
+
* @returns {object} clicked series id
|
|
634
|
+
*/
|
|
635
|
+
getSeriesIdByPosition(offset) {
|
|
636
|
+
const [clickedX, clickedY] = offset;
|
|
637
|
+
const chartRect = this.chartRect;
|
|
638
|
+
const labelOffset = this.labelOffset;
|
|
639
|
+
const aPos = {
|
|
640
|
+
x1: chartRect.x1 + labelOffset.left,
|
|
641
|
+
x2: chartRect.x2 - labelOffset.right,
|
|
642
|
+
y1: chartRect.y1 + labelOffset.top,
|
|
643
|
+
y2: chartRect.y2 - labelOffset.bottom,
|
|
644
|
+
};
|
|
645
|
+
const valueAxes = this.axesY[0];
|
|
646
|
+
const labelAxes = this.axesX[0];
|
|
647
|
+
const valueStartPoint = aPos[valueAxes.units.rectStart];
|
|
648
|
+
const valueEndPoint = aPos[valueAxes.units.rectEnd];
|
|
649
|
+
const labelStartPoint = aPos[labelAxes.units.rectStart];
|
|
650
|
+
const labelEndPoint = aPos[labelAxes.units.rectEnd];
|
|
651
|
+
|
|
652
|
+
const result = { sId: null };
|
|
653
|
+
|
|
654
|
+
if (clickedY > valueEndPoint && clickedY < valueStartPoint
|
|
655
|
+
&& clickedX < labelEndPoint && clickedX > labelStartPoint) {
|
|
656
|
+
let hitSeries;
|
|
657
|
+
let positionList;
|
|
658
|
+
const hitItem = this.findHitItem(offset);
|
|
659
|
+
const hitSeriesList = Object.keys(hitItem.items);
|
|
660
|
+
|
|
661
|
+
switch (this.options.type) {
|
|
662
|
+
case 'line': {
|
|
663
|
+
const orderedSeriesList = this.seriesInfo.charts.line;
|
|
664
|
+
const isStackChart = Object.values(this.seriesList).some(({ stackIndex }) => stackIndex);
|
|
665
|
+
|
|
666
|
+
if (hitSeriesList.length) { // 클릭한 위치에 data 가 존재하는 경우
|
|
667
|
+
if (isStackChart) {
|
|
668
|
+
positionList = orderedSeriesList.filter(sId => hitSeriesList.includes(sId))
|
|
669
|
+
.map(sId => ({ sId, position: hitItem.items[sId]?.data?.yp }));
|
|
670
|
+
hitSeries = positionList.find(({ position }) => clickedY > position)?.sId;
|
|
671
|
+
} else {
|
|
672
|
+
hitSeries = Object.entries(hitItem.items).find(([, { hit }]) => hit)?.[0];
|
|
673
|
+
}
|
|
674
|
+
} else { // 클릭한 위치에 data 가 존재하지 않는 경우
|
|
675
|
+
const visibleSeriesList = orderedSeriesList.filter(sId => this.seriesList[sId].show);
|
|
676
|
+
positionList = visibleSeriesList.map(sId => ({
|
|
677
|
+
sId,
|
|
678
|
+
position: this.seriesList[sId].data?.map(({ xp, yp }) => [xp, yp]),
|
|
679
|
+
}));
|
|
680
|
+
const dataIndex = positionList[0].position?.findIndex(([xp]) => xp >= clickedX);
|
|
681
|
+
const vectorList = positionList.map(({ sId, position }) => ({
|
|
682
|
+
sId,
|
|
683
|
+
vector: { start: position[dataIndex - 1], end: position[dataIndex] },
|
|
684
|
+
}));
|
|
685
|
+
|
|
686
|
+
// canvas 의 클릭 위치값은 제 4 사분면의 위치이므로 clickedY, y1, y2 의 값은 음수를 취한다.
|
|
687
|
+
if (isStackChart) {
|
|
688
|
+
hitSeries = vectorList.find(({ vector }) => {
|
|
689
|
+
const [x1, y1] = vector.start;
|
|
690
|
+
const [x2, y2] = vector.end;
|
|
691
|
+
const v1 = [x2 - x1, y1 - y2];
|
|
692
|
+
const v2 = [x2 - clickedX, clickedY - y2];
|
|
693
|
+
const xp = v1[0] * v2[1] - v1[1] * v2[0];
|
|
694
|
+
|
|
695
|
+
return vector.start.every(v => typeof v === 'number')
|
|
696
|
+
&& vector.end.every(v => typeof v === 'number')
|
|
697
|
+
&& xp > 0;
|
|
698
|
+
})?.sId;
|
|
699
|
+
} else {
|
|
700
|
+
hitSeries = vectorList.find(({ vector }) => {
|
|
701
|
+
const [x1, y1] = vector.start;
|
|
702
|
+
const [x2, y2] = vector.end;
|
|
703
|
+
const a = (y1 - y2) / (x2 - x1);
|
|
704
|
+
const b = -1;
|
|
705
|
+
const c = -y1 - a * x1;
|
|
706
|
+
const distance = Math.abs(a * clickedX - b * clickedY + c)
|
|
707
|
+
/ Math.sqrt(a ** 2 + b ** 2);
|
|
708
|
+
|
|
709
|
+
return distance < 3;
|
|
710
|
+
})?.sId;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
break;
|
|
714
|
+
}
|
|
715
|
+
default:
|
|
716
|
+
break;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
result.sId = hitSeries;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
return result;
|
|
723
|
+
},
|
|
676
724
|
/**
|
|
677
725
|
* Find label info by position x and y
|
|
678
726
|
* @param {array} offset position x and y
|