evui 3.3.8 → 3.3.11
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 +2982 -792
- package/dist/evui.common.js.map +1 -1
- package/dist/evui.umd.js +2982 -792
- 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 +86 -31
- package/src/components/chart/element/element.bar.js +9 -3
- package/src/components/chart/element/element.heatmap.js +213 -0
- package/src/components/chart/element/element.pie.js +75 -5
- package/src/components/chart/element/element.scatter.js +26 -9
- package/src/components/chart/element/element.tip.js +158 -13
- package/src/components/chart/helpers/helpers.constant.js +22 -0
- package/src/components/chart/model/model.series.js +4 -0
- package/src/components/chart/model/model.store.js +166 -2
- package/src/components/chart/plugins/plugins.interaction.js +78 -10
- package/src/components/chart/plugins/plugins.legend.js +213 -42
- package/src/components/chart/plugins/plugins.pie.js +2 -0
- package/src/components/chart/plugins/plugins.tooltip.js +249 -6
- package/src/components/chart/scale/scale.js +20 -2
- package/src/components/chart/scale/scale.step.js +20 -5
- package/src/components/chart/scale/scale.time.category.js +20 -2
- package/src/components/chart/uses.js +20 -3
- package/src/components/grid/Grid.vue +276 -132
- package/src/components/grid/grid.filter.window.vue +1 -0
- package/src/components/grid/grid.pagination.vue +75 -0
- package/src/components/grid/grid.summary.vue +221 -0
- package/src/components/grid/style/grid.scss +0 -14
- package/src/components/grid/uses.js +157 -78
- 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, selectItem } = 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,37 +181,76 @@ class EvChart {
|
|
|
177
181
|
for (let jx = 0; jx < chartTypeSet.length; jx++) {
|
|
178
182
|
const series = this.seriesList[chartTypeSet[jx]];
|
|
179
183
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (series.show) {
|
|
187
|
-
showIndex++;
|
|
184
|
+
switch (chartType) {
|
|
185
|
+
case 'line':
|
|
186
|
+
case 'heatMap': {
|
|
187
|
+
series.draw(opt);
|
|
188
|
+
break;
|
|
188
189
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
} else {
|
|
197
|
-
this.drawPie(selectInfo);
|
|
190
|
+
case 'bar': {
|
|
191
|
+
const { thickness, borderRadius } = this.options;
|
|
192
|
+
series.draw({ thickness, borderRadius, showSeriesCount, showIndex, ...opt });
|
|
193
|
+
if (series.show) {
|
|
194
|
+
showIndex++;
|
|
195
|
+
}
|
|
196
|
+
break;
|
|
198
197
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
198
|
+
case 'pie': {
|
|
199
|
+
const selectInfo = hitInfo
|
|
200
|
+
?? this.lastHitInfo
|
|
201
|
+
?? { sId: this.defaultSelectItemInfo?.seriesID };
|
|
202
|
+
|
|
203
|
+
if (this.options.sunburst) {
|
|
204
|
+
this.drawSunburst(selectInfo);
|
|
205
|
+
} else {
|
|
206
|
+
this.drawPie(selectInfo);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (this.options.doughnutHoleSize > 0) {
|
|
210
|
+
this.drawDoughnutHole();
|
|
211
|
+
}
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
case 'scatter': {
|
|
215
|
+
if (selectItem.use && selectItem.useSeriesOpacity) {
|
|
216
|
+
if (hitInfo) {
|
|
217
|
+
if (hitInfo?.maxIndex || hitInfo?.maxIndex === 0) {
|
|
218
|
+
opt.selectInfo = {
|
|
219
|
+
seriesID: hitInfo.sId,
|
|
220
|
+
dataIndex: hitInfo.maxIndex,
|
|
221
|
+
};
|
|
222
|
+
} else {
|
|
223
|
+
opt.selectInfo = null;
|
|
224
|
+
}
|
|
225
|
+
} else if (this.lastHitInfo?.maxIndex || this.lastHitInfo?.maxIndex === 0) {
|
|
226
|
+
opt.selectInfo = {
|
|
227
|
+
seriesID: this.lastHitInfo.sId,
|
|
228
|
+
dataIndex: this.lastHitInfo.maxIndex,
|
|
229
|
+
};
|
|
230
|
+
} else if (this.defaultSelectItemInfo?.dataIndex
|
|
231
|
+
|| this.defaultSelectItemInfo?.dataIndex === 0) {
|
|
232
|
+
opt.selectInfo = {
|
|
233
|
+
seriesID: this.defaultSelectItemInfo.seriesID,
|
|
234
|
+
dataIndex: this.defaultSelectItemInfo.dataIndex,
|
|
235
|
+
};
|
|
236
|
+
} else {
|
|
237
|
+
opt.selectInfo = null;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
series.draw(opt);
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
default: {
|
|
245
|
+
break;
|
|
202
246
|
}
|
|
203
|
-
break;
|
|
204
247
|
}
|
|
205
248
|
}
|
|
206
249
|
}
|
|
207
250
|
}
|
|
208
251
|
|
|
209
252
|
/**
|
|
210
|
-
* Draw Tip with hitInfo and
|
|
253
|
+
* Draw Tip with hitInfo and defaultSelectItemInfo
|
|
211
254
|
* @param hitInfo
|
|
212
255
|
*/
|
|
213
256
|
drawTip(hitInfo) {
|
|
@@ -221,8 +264,8 @@ class EvChart {
|
|
|
221
264
|
tipLocationInfo = hitInfo;
|
|
222
265
|
} else if (this.lastHitInfo) {
|
|
223
266
|
tipLocationInfo = this.lastHitInfo;
|
|
224
|
-
} else if (this.
|
|
225
|
-
tipLocationInfo = this.getItem(this.
|
|
267
|
+
} else if (this.defaultSelectItemInfo) {
|
|
268
|
+
tipLocationInfo = this.getItem(this.defaultSelectItemInfo, false);
|
|
226
269
|
} else {
|
|
227
270
|
tipLocationInfo = null;
|
|
228
271
|
}
|
|
@@ -281,11 +324,21 @@ class EvChart {
|
|
|
281
324
|
*/
|
|
282
325
|
drawAxis(hitInfo) {
|
|
283
326
|
this.axesX.forEach((axis, index) => {
|
|
284
|
-
axis.draw(
|
|
327
|
+
axis.draw(
|
|
328
|
+
this.chartRect,
|
|
329
|
+
this.labelOffset,
|
|
330
|
+
this.axesSteps.x[index],
|
|
331
|
+
hitInfo,
|
|
332
|
+
this.defaultSelectLabelInfo);
|
|
285
333
|
});
|
|
286
334
|
|
|
287
335
|
this.axesY.forEach((axis, index) => {
|
|
288
|
-
axis.draw(
|
|
336
|
+
axis.draw(
|
|
337
|
+
this.chartRect,
|
|
338
|
+
this.labelOffset,
|
|
339
|
+
this.axesSteps.y[index],
|
|
340
|
+
hitInfo,
|
|
341
|
+
this.defaultSelectLabelInfo);
|
|
289
342
|
});
|
|
290
343
|
}
|
|
291
344
|
|
|
@@ -545,6 +598,7 @@ class EvChart {
|
|
|
545
598
|
bar: [],
|
|
546
599
|
line: [],
|
|
547
600
|
scatter: [],
|
|
601
|
+
heatMap: [],
|
|
548
602
|
},
|
|
549
603
|
count: 0,
|
|
550
604
|
};
|
|
@@ -604,8 +658,9 @@ class EvChart {
|
|
|
604
658
|
this.axesY = this.createAxes('y', options.axesY);
|
|
605
659
|
this.axesRange = this.getAxesRange();
|
|
606
660
|
this.labelOffset = this.getLabelOffset();
|
|
661
|
+
this.initSelectedLabelInfo();
|
|
607
662
|
|
|
608
|
-
this.render();
|
|
663
|
+
this.render(updateInfo?.hitInfo);
|
|
609
664
|
|
|
610
665
|
const isDragMove = this.dragInfo && this.drawSelectionArea;
|
|
611
666
|
if (isDragMove) {
|
|
@@ -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(
|
|
@@ -332,7 +338,7 @@ class Bar {
|
|
|
332
338
|
*/
|
|
333
339
|
drawValueLabels({ context, data, positions, isHighlight }) {
|
|
334
340
|
const isHorizontal = this.isHorizontal;
|
|
335
|
-
const { fontSize, textColor, align, formatter } = this.showValue;
|
|
341
|
+
const { fontSize, textColor, align, formatter, decimalPoint } = this.showValue;
|
|
336
342
|
const { x, y, w, h } = positions;
|
|
337
343
|
const ctx = context;
|
|
338
344
|
|
|
@@ -361,7 +367,7 @@ class Bar {
|
|
|
361
367
|
}
|
|
362
368
|
|
|
363
369
|
if (!formatter || typeof formattedTxt !== 'string') {
|
|
364
|
-
formattedTxt = Util.labelSignFormat(value);
|
|
370
|
+
formattedTxt = Util.labelSignFormat(value, decimalPoint);
|
|
365
371
|
}
|
|
366
372
|
|
|
367
373
|
const vw = Math.round(ctx.measureText(formattedTxt).width);
|
|
@@ -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.floor(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;
|
|
@@ -24,9 +24,9 @@ class Pie {
|
|
|
24
24
|
this.centerX = 0;
|
|
25
25
|
this.centerY = 0;
|
|
26
26
|
this.radius = 0;
|
|
27
|
+
this.doughnutHoleSize = 0;
|
|
27
28
|
this.startAngle = 0;
|
|
28
29
|
this.endAngle = 0;
|
|
29
|
-
this.slice = null;
|
|
30
30
|
this.state = null;
|
|
31
31
|
this.ctx = null;
|
|
32
32
|
this.isSelect = false;
|
|
@@ -45,6 +45,7 @@ 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;
|
|
48
49
|
|
|
49
50
|
const color = this.color;
|
|
50
51
|
const noneDownplayOpacity = color.includes('rgba') ? Util.getOpacity(color) : 1;
|
|
@@ -64,9 +65,11 @@ class Pie {
|
|
|
64
65
|
ctx.stroke(slice);
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
if (this.showValue?.use) {
|
|
69
|
+
this.drawValueLabels(ctx, doughnutHoleRadius);
|
|
70
|
+
}
|
|
68
71
|
|
|
69
|
-
|
|
72
|
+
ctx.closePath();
|
|
70
73
|
this.ctx = ctx;
|
|
71
74
|
}
|
|
72
75
|
|
|
@@ -78,8 +81,19 @@ class Pie {
|
|
|
78
81
|
*/
|
|
79
82
|
findGraphData([offsetX, offsetY]) {
|
|
80
83
|
const item = { data: null, hit: false, color: null, index: -1 };
|
|
81
|
-
|
|
82
|
-
|
|
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) {
|
|
83
97
|
item.type = this.type;
|
|
84
98
|
item.data = this.data;
|
|
85
99
|
item.hit = true;
|
|
@@ -101,6 +115,7 @@ class Pie {
|
|
|
101
115
|
itemHighlight(item, context) {
|
|
102
116
|
const ctx = context;
|
|
103
117
|
const radius = this.isSelect ? this.radius + 5 : this.radius;
|
|
118
|
+
const doughnutHoleRadius = this.radius * this.doughnutHoleSize;
|
|
104
119
|
|
|
105
120
|
ctx.save();
|
|
106
121
|
ctx.shadowOffsetX = 0;
|
|
@@ -116,7 +131,62 @@ class Pie {
|
|
|
116
131
|
ctx.arc(this.centerX, this.centerY, radius, this.startAngle, this.endAngle);
|
|
117
132
|
ctx.lineTo(this.centerX, this.centerY);
|
|
118
133
|
ctx.fill();
|
|
134
|
+
|
|
135
|
+
if (this.showValue?.use) {
|
|
136
|
+
this.drawValueLabels(ctx, doughnutHoleRadius);
|
|
137
|
+
}
|
|
138
|
+
|
|
119
139
|
ctx.closePath();
|
|
140
|
+
ctx.restore();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Draw value label if series 'use' of showValue option is true
|
|
145
|
+
*
|
|
146
|
+
* @param context canvas context
|
|
147
|
+
*/
|
|
148
|
+
drawValueLabels(context) {
|
|
149
|
+
const { fontSize, textColor, formatter } = this.showValue;
|
|
150
|
+
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
|
+
const value = this.data.o;
|
|
162
|
+
|
|
163
|
+
let formattedTxt;
|
|
164
|
+
if (formatter) {
|
|
165
|
+
formattedTxt = formatter(value);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (!formatter || typeof formattedTxt !== 'string') {
|
|
169
|
+
formattedTxt = Util.labelSignFormat(value);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const ratio = 1.8;
|
|
173
|
+
const radius = this.radius - this.doughnutHoleSize;
|
|
174
|
+
const innerAngle = ((this.endAngle - this.startAngle) * 180) / Math.PI;
|
|
175
|
+
const valueHeight = fontSize + 4;
|
|
176
|
+
const valueWidth = Math.round(ctx.measureText(formattedTxt).width);
|
|
177
|
+
|
|
178
|
+
if (innerAngle >= valueWidth * ratio
|
|
179
|
+
&& innerAngle >= valueHeight * ratio
|
|
180
|
+
&& radius >= valueWidth * ratio
|
|
181
|
+
&& radius >= valueHeight * ratio
|
|
182
|
+
) {
|
|
183
|
+
const halfRadius = (radius / 2) + this.doughnutHoleSize;
|
|
184
|
+
const centerAngle = ((this.endAngle - this.startAngle) / 2) + this.startAngle;
|
|
185
|
+
const xPos = halfRadius * Math.cos(centerAngle) + this.centerX;
|
|
186
|
+
const yPos = halfRadius * Math.sin(centerAngle) + this.centerY;
|
|
187
|
+
|
|
188
|
+
ctx.fillText(formattedTxt, xPos, yPos);
|
|
189
|
+
}
|
|
120
190
|
|
|
121
191
|
ctx.restore();
|
|
122
192
|
}
|