evui 3.3.9 → 3.3.10
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 +2104 -689
- package/dist/evui.common.js.map +1 -1
- package/dist/evui.umd.js +2104 -689
- 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 +15 -6
- package/src/components/chart/chart.core.js +27 -11
- package/src/components/chart/element/element.bar.js +7 -1
- package/src/components/chart/element/element.heatmap.js +213 -0
- package/src/components/chart/element/element.pie.js +13 -5
- package/src/components/chart/element/element.tip.js +125 -4
- package/src/components/chart/helpers/helpers.constant.js +15 -0
- package/src/components/chart/model/model.series.js +4 -0
- package/src/components/chart/model/model.store.js +160 -2
- package/src/components/chart/plugins/plugins.interaction.js +73 -9
- package/src/components/chart/plugins/plugins.legend.js +212 -42
- package/src/components/chart/plugins/plugins.tooltip.js +86 -0
- package/src/components/chart/scale/scale.js +12 -2
- package/src/components/chart/scale/scale.step.js +12 -5
- package/src/components/chart/scale/scale.time.category.js +12 -2
- package/src/components/chart/uses.js +19 -3
- package/src/components/grid/Grid.vue +199 -116
- package/src/components/grid/grid.filter.window.vue +1 -0
- package/src/components/grid/grid.pagination.vue +75 -0
- package/src/components/grid/uses.js +103 -33
- package/src/components/pagination/Pagination.vue +20 -17
package/package.json
CHANGED
|
@@ -20,6 +20,10 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
|
|
|
20
20
|
type: Object,
|
|
21
21
|
default: null,
|
|
22
22
|
},
|
|
23
|
+
selectedLabel: {
|
|
24
|
+
type: Object,
|
|
25
|
+
default: null,
|
|
26
|
+
},
|
|
23
27
|
options: {
|
|
24
28
|
type: Object,
|
|
25
29
|
default: () => ({}),
|
|
@@ -38,6 +42,7 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
|
|
|
38
42
|
'dbl-click',
|
|
39
43
|
'drag-select',
|
|
40
44
|
'update:selectedItem',
|
|
45
|
+
'update:selectedLabel',
|
|
41
46
|
],
|
|
42
47
|
setup(props) {
|
|
43
48
|
let evChart = {};
|
|
@@ -45,7 +50,8 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
|
|
|
45
50
|
|
|
46
51
|
const {
|
|
47
52
|
eventListeners,
|
|
48
|
-
|
|
53
|
+
selectItemInfo,
|
|
54
|
+
selectLabelInfo,
|
|
49
55
|
getNormalizedData,
|
|
50
56
|
getNormalizedOptions,
|
|
51
57
|
} = useModel();
|
|
@@ -66,7 +72,8 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
|
|
|
66
72
|
normalizedData,
|
|
67
73
|
normalizedOptions,
|
|
68
74
|
eventListeners,
|
|
69
|
-
|
|
75
|
+
selectItemInfo,
|
|
76
|
+
selectLabelInfo,
|
|
70
77
|
);
|
|
71
78
|
};
|
|
72
79
|
|
|
@@ -102,13 +109,15 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
|
|
|
102
109
|
}, { deep: true });
|
|
103
110
|
|
|
104
111
|
await watch(() => props.selectedItem, (newValue) => {
|
|
105
|
-
if (!newValue?.seriesID) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
112
|
const chartType = props.options?.type;
|
|
110
113
|
evChart.selectItemByData(newValue, chartType);
|
|
111
114
|
}, { deep: true });
|
|
115
|
+
|
|
116
|
+
await watch(() => props.selectedLabel, (newValue) => {
|
|
117
|
+
if (newValue.dataIndex) {
|
|
118
|
+
evChart.renderWithSelectLabel(newValue.dataIndex);
|
|
119
|
+
}
|
|
120
|
+
}, { deep: true });
|
|
112
121
|
});
|
|
113
122
|
|
|
114
123
|
onBeforeUnmount(() => {
|
|
@@ -14,7 +14,7 @@ import Pie from './plugins/plugins.pie';
|
|
|
14
14
|
import Tip from './element/element.tip';
|
|
15
15
|
|
|
16
16
|
class EvChart {
|
|
17
|
-
constructor(target, data, options, listeners,
|
|
17
|
+
constructor(target, data, options, listeners, defaultSelectItemInfo, defaultSelectLabelInfo) {
|
|
18
18
|
Object.keys(Model).forEach(key => Object.assign(this, Model[key]));
|
|
19
19
|
Object.assign(this, Title);
|
|
20
20
|
Object.assign(this, Legend);
|
|
@@ -61,11 +61,12 @@ class EvChart {
|
|
|
61
61
|
this.seriesList = {};
|
|
62
62
|
this.lastTip = { pos: null, value: null };
|
|
63
63
|
this.seriesInfo = {
|
|
64
|
-
charts: { pie: [], bar: [], line: [], scatter: [] },
|
|
64
|
+
charts: { pie: [], bar: [], line: [], scatter: [], heatMap: [] },
|
|
65
65
|
count: 0,
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
-
this.
|
|
68
|
+
this.defaultSelectItemInfo = defaultSelectItemInfo;
|
|
69
|
+
this.defaultSelectLabelInfo = defaultSelectLabelInfo;
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
/**
|
|
@@ -92,6 +93,7 @@ class EvChart {
|
|
|
92
93
|
|
|
93
94
|
this.axesRange = this.getAxesRange();
|
|
94
95
|
this.labelOffset = this.getLabelOffset();
|
|
96
|
+
this.initSelectedLabelInfo();
|
|
95
97
|
|
|
96
98
|
this.drawChart();
|
|
97
99
|
|
|
@@ -146,11 +148,12 @@ class EvChart {
|
|
|
146
148
|
|
|
147
149
|
/**
|
|
148
150
|
* Draw each series
|
|
151
|
+
* @param {any} [hitInfo=undefined] from mousemove callback (object or undefined)
|
|
149
152
|
*
|
|
150
153
|
* @returns {undefined}
|
|
151
154
|
*/
|
|
152
155
|
drawSeries(hitInfo) {
|
|
153
|
-
const maxTip = this.options
|
|
156
|
+
const { maxTip, selectLabel } = this.options;
|
|
154
157
|
|
|
155
158
|
const opt = {
|
|
156
159
|
ctx: this.bufferCtx,
|
|
@@ -158,6 +161,7 @@ class EvChart {
|
|
|
158
161
|
labelOffset: this.labelOffset,
|
|
159
162
|
axesSteps: this.axesSteps,
|
|
160
163
|
maxTipOpt: { background: maxTip.background, color: maxTip.color },
|
|
164
|
+
selectLabel: { option: selectLabel, selected: this.defaultSelectLabelInfo },
|
|
161
165
|
};
|
|
162
166
|
|
|
163
167
|
let showIndex = 0;
|
|
@@ -177,7 +181,7 @@ class EvChart {
|
|
|
177
181
|
for (let jx = 0; jx < chartTypeSet.length; jx++) {
|
|
178
182
|
const series = this.seriesList[chartTypeSet[jx]];
|
|
179
183
|
|
|
180
|
-
if (chartType === 'line' || chartType === 'scatter') {
|
|
184
|
+
if (chartType === 'line' || chartType === 'scatter' || chartType === 'heatMap') {
|
|
181
185
|
series.draw(opt);
|
|
182
186
|
} else if (chartType === 'bar') {
|
|
183
187
|
const { thickness, borderRadius } = this.options;
|
|
@@ -189,7 +193,7 @@ class EvChart {
|
|
|
189
193
|
} else {
|
|
190
194
|
const selectInfo = hitInfo
|
|
191
195
|
?? this.lastHitInfo
|
|
192
|
-
?? { sId: this.
|
|
196
|
+
?? { sId: this.defaultSelectItemInfo?.seriesID };
|
|
193
197
|
|
|
194
198
|
if (this.options.sunburst) {
|
|
195
199
|
this.drawSunburst(selectInfo);
|
|
@@ -207,7 +211,7 @@ class EvChart {
|
|
|
207
211
|
}
|
|
208
212
|
|
|
209
213
|
/**
|
|
210
|
-
* Draw Tip with hitInfo and
|
|
214
|
+
* Draw Tip with hitInfo and defaultSelectItemInfo
|
|
211
215
|
* @param hitInfo
|
|
212
216
|
*/
|
|
213
217
|
drawTip(hitInfo) {
|
|
@@ -221,8 +225,8 @@ class EvChart {
|
|
|
221
225
|
tipLocationInfo = hitInfo;
|
|
222
226
|
} else if (this.lastHitInfo) {
|
|
223
227
|
tipLocationInfo = this.lastHitInfo;
|
|
224
|
-
} else if (this.
|
|
225
|
-
tipLocationInfo = this.getItem(this.
|
|
228
|
+
} else if (this.defaultSelectItemInfo) {
|
|
229
|
+
tipLocationInfo = this.getItem(this.defaultSelectItemInfo, false);
|
|
226
230
|
} else {
|
|
227
231
|
tipLocationInfo = null;
|
|
228
232
|
}
|
|
@@ -281,11 +285,21 @@ class EvChart {
|
|
|
281
285
|
*/
|
|
282
286
|
drawAxis(hitInfo) {
|
|
283
287
|
this.axesX.forEach((axis, index) => {
|
|
284
|
-
axis.draw(
|
|
288
|
+
axis.draw(
|
|
289
|
+
this.chartRect,
|
|
290
|
+
this.labelOffset,
|
|
291
|
+
this.axesSteps.x[index],
|
|
292
|
+
hitInfo,
|
|
293
|
+
this.defaultSelectLabelInfo);
|
|
285
294
|
});
|
|
286
295
|
|
|
287
296
|
this.axesY.forEach((axis, index) => {
|
|
288
|
-
axis.draw(
|
|
297
|
+
axis.draw(
|
|
298
|
+
this.chartRect,
|
|
299
|
+
this.labelOffset,
|
|
300
|
+
this.axesSteps.y[index],
|
|
301
|
+
hitInfo,
|
|
302
|
+
this.defaultSelectLabelInfo);
|
|
289
303
|
});
|
|
290
304
|
}
|
|
291
305
|
|
|
@@ -545,6 +559,7 @@ class EvChart {
|
|
|
545
559
|
bar: [],
|
|
546
560
|
line: [],
|
|
547
561
|
scatter: [],
|
|
562
|
+
heatMap: [],
|
|
548
563
|
},
|
|
549
564
|
count: 0,
|
|
550
565
|
};
|
|
@@ -604,6 +619,7 @@ class EvChart {
|
|
|
604
619
|
this.axesY = this.createAxes('y', options.axesY);
|
|
605
620
|
this.axesRange = this.getAxesRange();
|
|
606
621
|
this.labelOffset = this.getLabelOffset();
|
|
622
|
+
this.initSelectedLabelInfo();
|
|
607
623
|
|
|
608
624
|
this.render();
|
|
609
625
|
|
|
@@ -131,7 +131,13 @@ class Bar {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
const barColor = item.dataColor || this.color;
|
|
134
|
-
|
|
134
|
+
|
|
135
|
+
const selectLabelOption = param.selectLabel.option;
|
|
136
|
+
const selectedLabel = param.selectLabel.selected ?? { dataIndex: [] };
|
|
137
|
+
|
|
138
|
+
const isDownplay = selectLabelOption.use && selectLabelOption.useSeriesOpacity
|
|
139
|
+
? selectedLabel.dataIndex.length && !selectedLabel.dataIndex.includes(index)
|
|
140
|
+
: this.state === 'downplay';
|
|
135
141
|
|
|
136
142
|
if (typeof barColor !== 'string') {
|
|
137
143
|
ctx.fillStyle = Canvas.createGradient(
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { merge } from 'lodash-es';
|
|
2
|
+
import Canvas from '../helpers/helpers.canvas';
|
|
3
|
+
import Util from '../helpers/helpers.util';
|
|
4
|
+
import { COLOR, HEAT_MAP_OPTION } from '../helpers/helpers.constant';
|
|
5
|
+
|
|
6
|
+
class HeatMap {
|
|
7
|
+
constructor(sId, opt, sIdx) {
|
|
8
|
+
const merged = merge({}, HEAT_MAP_OPTION, opt);
|
|
9
|
+
Object.keys(merged).forEach((key) => {
|
|
10
|
+
this[key] = merged[key];
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
['color', 'pointFill', 'fillColor'].forEach((colorProp) => {
|
|
14
|
+
if (this[colorProp] === undefined) {
|
|
15
|
+
this[colorProp] = COLOR[sIdx];
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
this.colorAxis = this.createColorAxis(opt.colorOpt);
|
|
20
|
+
this.errorColor = opt.colorOpt.error;
|
|
21
|
+
this.borderColor = opt.colorOpt.border;
|
|
22
|
+
|
|
23
|
+
this.sId = sId;
|
|
24
|
+
this.data = [];
|
|
25
|
+
this.spaces = opt.spaces || { x: null, y: null };
|
|
26
|
+
this.size = {
|
|
27
|
+
w: 0,
|
|
28
|
+
h: 0,
|
|
29
|
+
};
|
|
30
|
+
this.valueOpt = {
|
|
31
|
+
max: 0,
|
|
32
|
+
interval: 0,
|
|
33
|
+
};
|
|
34
|
+
this.type = 'heatMap';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* create series color axis
|
|
39
|
+
* @param colorOpt
|
|
40
|
+
* @returns {*[]}
|
|
41
|
+
*/
|
|
42
|
+
createColorAxis(colorOpt) {
|
|
43
|
+
const colorAxis = [];
|
|
44
|
+
const { min, max, categoryCnt } = colorOpt;
|
|
45
|
+
|
|
46
|
+
const minColor = min.includes('#') ? Util.hexToRgb(min) : min;
|
|
47
|
+
const maxColor = max.includes('#') ? Util.hexToRgb(max) : max;
|
|
48
|
+
|
|
49
|
+
const [minR, minG, minB] = minColor.split(',');
|
|
50
|
+
const [maxR, maxG, maxB] = maxColor.split(',');
|
|
51
|
+
|
|
52
|
+
const unitR = Math.floor((minR - maxR) / (categoryCnt - 1));
|
|
53
|
+
const unitG = Math.floor((minG - maxG) / (categoryCnt - 1));
|
|
54
|
+
const unitB = Math.floor((minB - maxB) / (categoryCnt - 1));
|
|
55
|
+
|
|
56
|
+
for (let ix = 0; ix < categoryCnt; ix++) {
|
|
57
|
+
const r = +minR - (unitR * ix);
|
|
58
|
+
const g = +minG - (unitG * ix);
|
|
59
|
+
const b = +minB - (unitB * ix);
|
|
60
|
+
|
|
61
|
+
colorAxis.push({
|
|
62
|
+
id: `color#${ix}`,
|
|
63
|
+
value: `rgb(${r},${g},${b})`,
|
|
64
|
+
state: 'normal',
|
|
65
|
+
show: true,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return colorAxis;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getColorIndex(value) {
|
|
73
|
+
const existError = this.valueOpt.existError;
|
|
74
|
+
const maxIndex = this.colorAxis.length;
|
|
75
|
+
if (value < 0) {
|
|
76
|
+
return maxIndex - 1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const colorIndex = Math.floor(value / this.valueOpt.interval);
|
|
80
|
+
if (colorIndex >= maxIndex) {
|
|
81
|
+
return existError ? maxIndex - 2 : maxIndex - 1;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return colorIndex;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
drawItem(ctx, xp, yp) {
|
|
88
|
+
ctx.beginPath();
|
|
89
|
+
ctx.strokeRect(xp - this.size.w, yp + Math.SQRT2, this.size.w, this.size.h);
|
|
90
|
+
ctx.fillRect(xp - this.size.w, yp + Math.SQRT2, this.size.w, this.size.h);
|
|
91
|
+
ctx.closePath();
|
|
92
|
+
ctx.stroke();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
draw(param) {
|
|
96
|
+
if (!this.show) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const { ctx, chartRect, labelOffset, axesSteps } = param;
|
|
101
|
+
|
|
102
|
+
const minmaxX = axesSteps.x[this.xAxisIndex];
|
|
103
|
+
const minmaxY = axesSteps.y[this.yAxisIndex];
|
|
104
|
+
|
|
105
|
+
const xArea = chartRect.chartWidth - (labelOffset.left + labelOffset.right);
|
|
106
|
+
const yArea = chartRect.chartHeight - (labelOffset.top + labelOffset.bottom);
|
|
107
|
+
|
|
108
|
+
const xsp = chartRect.x1 + labelOffset.left;
|
|
109
|
+
const ysp = chartRect.y2 - labelOffset.bottom;
|
|
110
|
+
|
|
111
|
+
this.size.w = Math.ceil(xArea / (this.spaces.x || (minmaxX.graphMax - minmaxX.graphMin)));
|
|
112
|
+
this.size.h = Math.floor(yArea / (this.spaces.y || (minmaxY.graphMax - minmaxY.graphMin)));
|
|
113
|
+
|
|
114
|
+
this.data.forEach((item) => {
|
|
115
|
+
item.xp = Canvas.calculateX(item.x, minmaxX.graphMin, minmaxX.graphMax, xArea, xsp);
|
|
116
|
+
item.yp = Canvas.calculateY(item.y, minmaxY.graphMin, minmaxY.graphMax, yArea, ysp);
|
|
117
|
+
|
|
118
|
+
const { xp, yp, o: value } = item;
|
|
119
|
+
|
|
120
|
+
if (xp !== null && yp !== null) {
|
|
121
|
+
const colorIndex = this.getColorIndex(value);
|
|
122
|
+
const opacity = this.colorAxis[colorIndex].state === 'downplay' ? 0.1 : 1;
|
|
123
|
+
item.dataColor = value < 0 ? this.errorColor : this.colorAxis[colorIndex].value;
|
|
124
|
+
item.cId = this.colorAxis[colorIndex].id;
|
|
125
|
+
if (this.colorAxis[colorIndex].show) {
|
|
126
|
+
ctx.strokeStyle = Util.colorStringToRgba(this.borderColor, opacity);
|
|
127
|
+
ctx.fillStyle = Util.colorStringToRgba(item.dataColor, opacity);
|
|
128
|
+
this.drawItem(ctx, xp, yp);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
*Returns items in range
|
|
136
|
+
* @param {object} params range values
|
|
137
|
+
*
|
|
138
|
+
* @returns {array}
|
|
139
|
+
*/
|
|
140
|
+
findItems({ xsp, ysp, width, height }) {
|
|
141
|
+
const gdata = this.data;
|
|
142
|
+
const xep = xsp + width;
|
|
143
|
+
const yep = ysp + height;
|
|
144
|
+
return gdata.filter(seriesData =>
|
|
145
|
+
(xsp - 1 <= seriesData.xp && seriesData.xp <= xep + 1
|
|
146
|
+
&& ysp - 1 <= seriesData.yp && seriesData.yp <= yep + 1));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Draw item highlight
|
|
151
|
+
* @param {object} item object for drawing series data
|
|
152
|
+
* @param {object} context canvas context
|
|
153
|
+
*
|
|
154
|
+
* @returns {undefined}
|
|
155
|
+
*/
|
|
156
|
+
itemHighlight(item, context) {
|
|
157
|
+
const gdata = item.data;
|
|
158
|
+
const ctx = context;
|
|
159
|
+
|
|
160
|
+
const x = gdata.xp;
|
|
161
|
+
const y = gdata.yp;
|
|
162
|
+
|
|
163
|
+
ctx.save();
|
|
164
|
+
if (x !== null && y !== null) {
|
|
165
|
+
const color = gdata.dataColor;
|
|
166
|
+
ctx.strokeStyle = Util.colorStringToRgba(color, 1);
|
|
167
|
+
ctx.fillStyle = Util.colorStringToRgba(color, this.highlight.maxShadowOpacity);
|
|
168
|
+
this.drawItem(ctx, x, y);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
ctx.restore();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Find graph item for tooltip
|
|
176
|
+
* @param {array} offset mouse position
|
|
177
|
+
*
|
|
178
|
+
* @returns {object} graph item
|
|
179
|
+
*/
|
|
180
|
+
findGraphData(offset) {
|
|
181
|
+
const xp = offset[0];
|
|
182
|
+
const yp = offset[1];
|
|
183
|
+
const item = {
|
|
184
|
+
data: null,
|
|
185
|
+
hit: false,
|
|
186
|
+
color: null,
|
|
187
|
+
name: null,
|
|
188
|
+
};
|
|
189
|
+
const wSize = this.size.w;
|
|
190
|
+
const hSize = this.size.h;
|
|
191
|
+
const gdata = this.data;
|
|
192
|
+
|
|
193
|
+
const foundItem = gdata.find((data) => {
|
|
194
|
+
const x = data.xp;
|
|
195
|
+
const y = data.yp;
|
|
196
|
+
|
|
197
|
+
return (x - wSize <= xp)
|
|
198
|
+
&& (xp <= x)
|
|
199
|
+
&& (y <= yp)
|
|
200
|
+
&& (yp <= y + hSize);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
if (foundItem) {
|
|
204
|
+
item.data = foundItem;
|
|
205
|
+
item.color = foundItem.dataColor;
|
|
206
|
+
item.hit = true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return item;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export default HeatMap;
|
|
@@ -27,7 +27,6 @@ class Pie {
|
|
|
27
27
|
this.doughnutHoleSize = 0;
|
|
28
28
|
this.startAngle = 0;
|
|
29
29
|
this.endAngle = 0;
|
|
30
|
-
this.slice = null;
|
|
31
30
|
this.state = null;
|
|
32
31
|
this.ctx = null;
|
|
33
32
|
this.isSelect = false;
|
|
@@ -71,8 +70,6 @@ class Pie {
|
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
ctx.closePath();
|
|
74
|
-
|
|
75
|
-
this.slice = slice;
|
|
76
73
|
this.ctx = ctx;
|
|
77
74
|
}
|
|
78
75
|
|
|
@@ -84,8 +81,19 @@ class Pie {
|
|
|
84
81
|
*/
|
|
85
82
|
findGraphData([offsetX, offsetY]) {
|
|
86
83
|
const item = { data: null, hit: false, color: null, index: -1 };
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
const {
|
|
85
|
+
radius,
|
|
86
|
+
startAngle,
|
|
87
|
+
endAngle,
|
|
88
|
+
centerX,
|
|
89
|
+
centerY,
|
|
90
|
+
} = this;
|
|
91
|
+
|
|
92
|
+
const distance = Math.sqrt((offsetX - centerX) ** 2 + (offsetY - centerY) ** 2);
|
|
93
|
+
const radian = (2.5 * Math.PI) - Math.atan2((offsetX - centerX), (offsetY - centerY));
|
|
94
|
+
const isPointInPath = radius > distance && radian >= startAngle && radian <= endAngle;
|
|
95
|
+
|
|
96
|
+
if (this.show && isPointInPath) {
|
|
89
97
|
item.type = this.type;
|
|
90
98
|
item.data = this.data;
|
|
91
99
|
item.hit = true;
|
|
@@ -14,9 +14,15 @@ const modules = {
|
|
|
14
14
|
const isHorizontal = !!opt.horizontal;
|
|
15
15
|
const maxTipOpt = opt.maxTip;
|
|
16
16
|
const selTipOpt = opt.selectItem;
|
|
17
|
+
const labelTipOpt = opt.selectLabel;
|
|
17
18
|
let maxArgs;
|
|
19
|
+
let isExistSelectedLabel;
|
|
18
20
|
|
|
19
|
-
if (
|
|
21
|
+
if (labelTipOpt.use && labelTipOpt.showTip) {
|
|
22
|
+
isExistSelectedLabel = this.drawLabelTip();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (selTipOpt.use && tipLocationInfo && !isExistSelectedLabel) {
|
|
20
26
|
const seriesInfo = this.seriesList[tipLocationInfo?.sId];
|
|
21
27
|
|
|
22
28
|
if (!seriesInfo?.show) {
|
|
@@ -57,8 +63,7 @@ const modules = {
|
|
|
57
63
|
this.lastHitInfo = tipLocationInfo;
|
|
58
64
|
}
|
|
59
65
|
}
|
|
60
|
-
|
|
61
|
-
if (maxTipOpt.use) {
|
|
66
|
+
if (maxTipOpt.use && !isExistSelectedLabel) {
|
|
62
67
|
const maxSID = this.minMax[isHorizontal ? 'x' : 'y'][0].maxSID;
|
|
63
68
|
maxArgs = this.calculateTipInfo(this.seriesList[maxSID], 'max', null);
|
|
64
69
|
|
|
@@ -76,7 +81,8 @@ const modules = {
|
|
|
76
81
|
/**
|
|
77
82
|
* Calculate tip size and contents
|
|
78
83
|
* @param {object} series series information (max series or selected series)
|
|
79
|
-
* @param {string} tipType tip type
|
|
84
|
+
* @param {string} tipType tip type
|
|
85
|
+
* [sel = user select series, label = user select label, max = max value]
|
|
80
86
|
* @param {object} hitInfo mouse hit information
|
|
81
87
|
*
|
|
82
88
|
* @returns {object} size and tip contents
|
|
@@ -220,6 +226,121 @@ const modules = {
|
|
|
220
226
|
ctx.closePath();
|
|
221
227
|
},
|
|
222
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Draw Selected Label Tip
|
|
231
|
+
* @returns {boolean} Whether drew at least one tip
|
|
232
|
+
*/
|
|
233
|
+
drawLabelTip() {
|
|
234
|
+
const opt = this.options;
|
|
235
|
+
const isHorizontal = !!opt.horizontal;
|
|
236
|
+
const labelTipOpt = opt.selectLabel;
|
|
237
|
+
const { dataIndex, data } = this.defaultSelectLabelInfo;
|
|
238
|
+
let drawTip = false;
|
|
239
|
+
|
|
240
|
+
if (dataIndex.length) {
|
|
241
|
+
drawTip = true;
|
|
242
|
+
|
|
243
|
+
const chartRect = this.chartRect;
|
|
244
|
+
const labelOffset = this.labelOffset;
|
|
245
|
+
const aPos = {
|
|
246
|
+
x1: chartRect.x1 + labelOffset.left,
|
|
247
|
+
x2: chartRect.x2 - labelOffset.right,
|
|
248
|
+
y1: chartRect.y1 + labelOffset.top,
|
|
249
|
+
y2: chartRect.y2 - labelOffset.bottom,
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const labelAxes = this.options.horizontal ? this.axesY[0] : this.axesX[0];
|
|
253
|
+
const labelStartPoint = aPos[labelAxes.units.rectStart];
|
|
254
|
+
const labelEndPoint = aPos[labelAxes.units.rectEnd];
|
|
255
|
+
const labelGap = (labelEndPoint - labelStartPoint) / labelAxes.labels.length;
|
|
256
|
+
|
|
257
|
+
const valueAxes = this.options.horizontal ? this.axesX[0] : this.axesY[0];
|
|
258
|
+
const valueStartPoint = aPos[valueAxes.units.rectStart];
|
|
259
|
+
|
|
260
|
+
const offset = this.options.type === 'bar' ? 4 : 6;
|
|
261
|
+
const chartWidth = chartRect.chartWidth - (labelOffset.left + labelOffset.right);
|
|
262
|
+
const chartHeight = chartRect.chartHeight - (labelOffset.top + labelOffset.bottom);
|
|
263
|
+
|
|
264
|
+
dataIndex.forEach((idx, i) => {
|
|
265
|
+
const labelCenter = Math.round(labelStartPoint + (labelGap * idx));
|
|
266
|
+
let gp;
|
|
267
|
+
const dp = labelCenter + (labelGap / 2);
|
|
268
|
+
if (labelTipOpt.fixedPosTop) {
|
|
269
|
+
if (isHorizontal) {
|
|
270
|
+
gp = Canvas.calculateX(
|
|
271
|
+
this.axesRange.x[0].max,
|
|
272
|
+
this.axesRange.x[0].min,
|
|
273
|
+
this.axesRange.x[0].max,
|
|
274
|
+
chartWidth,
|
|
275
|
+
valueStartPoint);
|
|
276
|
+
gp += offset;
|
|
277
|
+
} else {
|
|
278
|
+
gp = Canvas.calculateY(
|
|
279
|
+
this.axesRange.y[0].max,
|
|
280
|
+
this.axesRange.y[0].min,
|
|
281
|
+
this.axesRange.y[0].max,
|
|
282
|
+
chartHeight,
|
|
283
|
+
valueStartPoint);
|
|
284
|
+
gp -= offset;
|
|
285
|
+
}
|
|
286
|
+
} else if (isHorizontal) {
|
|
287
|
+
const seriesList = Object.keys(data[i] ?? {});
|
|
288
|
+
const visibleSeries = seriesList.filter(sId => this.seriesList[sId].show);
|
|
289
|
+
const visibleValue = visibleSeries.map(sId => data[i][sId]);
|
|
290
|
+
const isExistGrp = seriesList.some(sId => this.seriesList[sId].isExistGrp);
|
|
291
|
+
|
|
292
|
+
let maxValue;
|
|
293
|
+
if (isExistGrp) {
|
|
294
|
+
maxValue = visibleValue.reduce((acc, v) => acc + v) ?? 0;
|
|
295
|
+
} else if (visibleValue.length) {
|
|
296
|
+
maxValue = Math.max(...visibleValue);
|
|
297
|
+
} else {
|
|
298
|
+
maxValue = this.axesRange.x[0].max;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
gp = Canvas.calculateX(
|
|
302
|
+
maxValue,
|
|
303
|
+
this.axesRange.x[0].min,
|
|
304
|
+
this.axesRange.x[0].max,
|
|
305
|
+
chartWidth,
|
|
306
|
+
valueStartPoint);
|
|
307
|
+
gp += offset;
|
|
308
|
+
} else {
|
|
309
|
+
const seriesList = Object.keys(data[i] ?? {});
|
|
310
|
+
const visibleSeries = seriesList.filter(sId => this.seriesList[sId].show);
|
|
311
|
+
const visibleValue = visibleSeries.map(sId => data[i][sId]);
|
|
312
|
+
const isExistGrp = seriesList.some(sId => this.seriesList[sId].isExistGrp);
|
|
313
|
+
|
|
314
|
+
let maxValue;
|
|
315
|
+
if (isExistGrp) {
|
|
316
|
+
maxValue = visibleValue.reduce((acc, v) => acc + v) ?? 0;
|
|
317
|
+
} else if (visibleValue.length) {
|
|
318
|
+
maxValue = Math.max(...visibleValue);
|
|
319
|
+
} else {
|
|
320
|
+
maxValue = this.axesRange.y[0].max;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
gp = Canvas.calculateY(
|
|
324
|
+
maxValue,
|
|
325
|
+
this.axesRange.y[0].min,
|
|
326
|
+
this.axesRange.y[0].max,
|
|
327
|
+
chartHeight,
|
|
328
|
+
valueStartPoint);
|
|
329
|
+
gp -= offset;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
this.showTip({
|
|
333
|
+
context: this.bufferCtx,
|
|
334
|
+
x: isHorizontal ? gp : dp,
|
|
335
|
+
y: isHorizontal ? dp : gp,
|
|
336
|
+
opt: labelTipOpt,
|
|
337
|
+
isSamePos: false,
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return drawTip;
|
|
343
|
+
},
|
|
223
344
|
/**
|
|
224
345
|
* Calculate x, y position to draw text tip
|
|
225
346
|
* @param {object} param object for drawing text tip
|
|
@@ -128,6 +128,21 @@ export const PLOT_BAND_OPTION = {
|
|
|
128
128
|
color: '#FAE59D',
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
+
export const HEAT_MAP_OPTION = {
|
|
132
|
+
...LINE_OPTION,
|
|
133
|
+
colorOpt: {
|
|
134
|
+
min: '#FFFFFF',
|
|
135
|
+
max: '#0052FF',
|
|
136
|
+
categoryCnt: 5,
|
|
137
|
+
border: '#FFFFFF',
|
|
138
|
+
error: '#FF0000',
|
|
139
|
+
},
|
|
140
|
+
spaces: {
|
|
141
|
+
x: 0,
|
|
142
|
+
y: 0,
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
|
|
131
146
|
|
|
132
147
|
export const TIME_INTERVALS = {
|
|
133
148
|
millisecond: {
|
|
@@ -3,6 +3,7 @@ import Scatter from '../element/element.scatter';
|
|
|
3
3
|
import Bar from '../element/element.bar';
|
|
4
4
|
import TimeBar from '../element/element.bar.time';
|
|
5
5
|
import Pie from '../element/element.pie';
|
|
6
|
+
import HeatMap from '../element/element.heatmap';
|
|
6
7
|
|
|
7
8
|
const modules = {
|
|
8
9
|
/**
|
|
@@ -51,6 +52,9 @@ const modules = {
|
|
|
51
52
|
} else if (type === 'pie') {
|
|
52
53
|
this.seriesInfo.charts.pie.push(id);
|
|
53
54
|
return new Pie(id, opt, index);
|
|
55
|
+
} else if (type === 'heatMap') {
|
|
56
|
+
this.seriesInfo.charts.heatMap.push(id);
|
|
57
|
+
return new HeatMap(id, opt, index);
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
return false;
|