evui 3.3.36 → 3.3.39
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/LICENSE +21 -21
- package/README.md +40 -40
- package/dist/evui.common.js +1907 -1832
- package/dist/evui.common.js.map +1 -1
- package/dist/evui.umd.js +1907 -1832
- 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/dist/img/{EVUI.7f3588fb.svg → EVUI.b82ee81a.svg} +292 -292
- package/dist/img/{icon_mysql.7ea26d5d.svg → icon_mysql.1085fdc9.svg} +78 -78
- package/dist/img/{icon_oracle.9009b108.svg → icon_oracle.0572d3ee.svg} +13 -13
- package/dist/img/{icon_postgresql.f8fffba9.svg → icon_postgresql.ee12bde8.svg} +58 -58
- package/package.json +61 -61
- package/src/common/emitter.js +20 -20
- package/src/common/utils.debounce.js +223 -223
- package/src/common/utils.js +134 -134
- package/src/common/utils.table.js +78 -78
- package/src/common/utils.throttle.js +83 -83
- package/src/common/utils.tree.js +18 -18
- package/src/components/button/Button.vue +198 -198
- package/src/components/button/index.js +7 -7
- package/src/components/buttonGroup/ButtonGroup.vue +11 -11
- package/src/components/buttonGroup/index.js +7 -7
- package/src/components/calendar/Calendar.vue +661 -661
- package/src/components/calendar/index.js +7 -7
- package/src/components/calendar/uses.js +1272 -1272
- package/src/components/chart/Chart.vue +189 -192
- package/src/components/chart/chart.core.js +870 -870
- package/src/components/chart/element/element.bar.js +524 -524
- package/src/components/chart/element/element.bar.time.js +156 -156
- package/src/components/chart/element/element.heatmap.js +533 -533
- package/src/components/chart/element/element.line.js +339 -339
- package/src/components/chart/element/element.pie.js +197 -197
- package/src/components/chart/element/element.scatter.js +184 -184
- package/src/components/chart/element/element.tip.js +550 -542
- package/src/components/chart/helpers/helpers.canvas.js +265 -265
- package/src/components/chart/helpers/helpers.constant.js +206 -206
- package/src/components/chart/helpers/helpers.util.js +346 -338
- package/src/components/chart/index.js +9 -9
- package/src/components/chart/model/index.js +4 -4
- package/src/components/chart/model/model.series.js +93 -93
- package/src/components/chart/model/model.store.js +977 -967
- package/src/components/chart/plugins/plugins.interaction.js +769 -769
- package/src/components/chart/plugins/plugins.legend.gradient.js +602 -602
- package/src/components/chart/plugins/plugins.legend.js +1155 -1151
- package/src/components/chart/plugins/plugins.pie.js +254 -254
- package/src/components/chart/plugins/plugins.title.js +56 -56
- package/src/components/chart/plugins/plugins.tooltip.js +692 -692
- package/src/components/chart/scale/scale.js +848 -848
- package/src/components/chart/scale/scale.linear.js +38 -38
- package/src/components/chart/scale/scale.logarithmic.js +128 -128
- package/src/components/chart/scale/scale.step.js +336 -336
- package/src/components/chart/scale/scale.time.category.js +277 -277
- package/src/components/chart/scale/scale.time.js +48 -48
- package/src/components/chart/style/chart.scss +312 -312
- package/src/components/chart/uses.js +264 -252
- package/src/components/checkbox/Checkbox.vue +200 -200
- package/src/components/checkbox/index.js +7 -7
- package/src/components/checkboxGroup/CheckboxGroup.vue +44 -44
- package/src/components/checkboxGroup/index.js +7 -7
- package/src/components/contextMenu/ContextMenu.vue +80 -80
- package/src/components/contextMenu/MenuList.vue +149 -149
- package/src/components/contextMenu/index.js +7 -7
- package/src/components/contextMenu/uses.js +203 -203
- package/src/components/datePicker/DatePicker.vue +437 -437
- package/src/components/datePicker/index.js +7 -7
- package/src/components/datePicker/uses.js +419 -419
- package/src/components/grid/Grid.vue +827 -827
- package/src/components/grid/grid.filter.window.vue +493 -493
- package/src/components/grid/grid.pagination.vue +75 -75
- package/src/components/grid/grid.summary.vue +265 -265
- package/src/components/grid/grid.toolbar.vue +26 -26
- package/src/components/grid/index.js +11 -11
- package/src/components/grid/style/grid.scss +263 -263
- package/src/components/grid/uses.js +1002 -1007
- package/src/components/icon/Icon.vue +49 -49
- package/src/components/icon/index.js +8 -8
- package/src/components/inputNumber/InputNumber.vue +212 -212
- package/src/components/inputNumber/index.js +7 -7
- package/src/components/inputNumber/uses.js +217 -217
- package/src/components/loading/Loading.vue +125 -125
- package/src/components/loading/index.js +7 -7
- package/src/components/menu/Menu.vue +68 -68
- package/src/components/menu/MenuItem.vue +187 -187
- package/src/components/menu/index.js +7 -7
- package/src/components/message/Message.vue +223 -223
- package/src/components/message/index.js +31 -31
- package/src/components/messageBox/MessageBox.vue +358 -358
- package/src/components/messageBox/index.js +22 -22
- package/src/components/notification/Notification.vue +316 -316
- package/src/components/notification/index.js +49 -49
- package/src/components/pagination/Pagination.vue +271 -271
- package/src/components/pagination/index.js +7 -7
- package/src/components/pagination/pageButton.vue +30 -30
- package/src/components/progress/Progress.vue +139 -139
- package/src/components/progress/index.js +7 -7
- package/src/components/radio/Radio.vue +159 -159
- package/src/components/radio/index.js +7 -7
- package/src/components/radioGroup/RadioGroup.vue +41 -41
- package/src/components/radioGroup/index.js +7 -7
- package/src/components/scheduler/Scheduler.vue +149 -149
- package/src/components/scheduler/index.js +7 -7
- package/src/components/scheduler/uses.js +183 -183
- package/src/components/select/Select.vue +440 -440
- package/src/components/select/index.js +7 -7
- package/src/components/select/uses.js +270 -270
- package/src/components/slider/Slider.vue +505 -505
- package/src/components/slider/index.js +7 -7
- package/src/components/slider/uses.js +390 -390
- package/src/components/tabPanel/TabPanel.vue +74 -74
- package/src/components/tabPanel/index.js +7 -7
- package/src/components/tabs/Tabs.vue +517 -517
- package/src/components/tabs/index.js +7 -7
- package/src/components/textField/TextField.vue +375 -375
- package/src/components/textField/index.js +7 -7
- package/src/components/timePicker/TimePicker.vue +352 -352
- package/src/components/timePicker/index.js +7 -7
- package/src/components/toggle/Toggle.vue +115 -115
- package/src/components/toggle/index.js +7 -7
- package/src/components/tree/Tree.vue +313 -313
- package/src/components/tree/TreeNode.vue +293 -293
- package/src/components/tree/index.js +7 -7
- package/src/components/treeGrid/TreeGrid.vue +758 -758
- package/src/components/treeGrid/TreeGridNode.vue +275 -275
- package/src/components/treeGrid/index.js +9 -9
- package/src/components/treeGrid/style/treeGrid.scss +261 -261
- package/src/components/treeGrid/treeGrid.toolbar.vue +26 -26
- package/src/components/treeGrid/uses.js +867 -867
- package/src/components/window/Window.vue +329 -329
- package/src/components/window/index.js +7 -7
- package/src/components/window/uses.js +899 -899
- package/src/directives/clickoutside.js +90 -90
- package/src/main.js +116 -116
- package/src/style/components/input.scss +108 -108
- package/src/style/functions.scss +3 -3
- package/src/style/index.scss +6 -6
- package/src/style/lib/fonts/EVUI.svg +292 -292
- package/src/style/lib/icon.css +888 -888
- package/src/style/mixins.scss +94 -94
- package/src/style/themes.scss +67 -67
- package/src/style/variables.scss +22 -22
|
@@ -1,524 +1,524 @@
|
|
|
1
|
-
import { defaultsDeep } from 'lodash-es';
|
|
2
|
-
import { truthy } from '@/common/utils';
|
|
3
|
-
import { COLOR, BAR_OPTION } from '../helpers/helpers.constant';
|
|
4
|
-
import Canvas from '../helpers/helpers.canvas';
|
|
5
|
-
import Util from '../helpers/helpers.util';
|
|
6
|
-
|
|
7
|
-
class Bar {
|
|
8
|
-
constructor(sId, opt, sIdx, isHorizontal) {
|
|
9
|
-
const merged = defaultsDeep({}, opt, BAR_OPTION);
|
|
10
|
-
Object.keys(merged).forEach((key) => {
|
|
11
|
-
this[key] = merged[key];
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
if (this.name === undefined) {
|
|
15
|
-
this.name = `series-${sIdx}`;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (this.color === undefined) {
|
|
19
|
-
this.color = COLOR[sIdx];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
this.type = 'bar';
|
|
23
|
-
this.sId = sId;
|
|
24
|
-
this.data = [];
|
|
25
|
-
this.isHorizontal = isHorizontal;
|
|
26
|
-
this.size = {
|
|
27
|
-
cat: 0,
|
|
28
|
-
bar: 0,
|
|
29
|
-
cPad: 0,
|
|
30
|
-
bPad: 0,
|
|
31
|
-
w: 0,
|
|
32
|
-
h: 0,
|
|
33
|
-
ix: 0,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Draw series data
|
|
39
|
-
* @param {object} param object for drawing series data
|
|
40
|
-
*
|
|
41
|
-
* @returns {undefined}
|
|
42
|
-
*/
|
|
43
|
-
draw(param) {
|
|
44
|
-
if (!this.show) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const { isHorizontal, showValue } = this;
|
|
49
|
-
|
|
50
|
-
const ctx = param.ctx;
|
|
51
|
-
const chartRect = param.chartRect;
|
|
52
|
-
const labelOffset = param.labelOffset;
|
|
53
|
-
const axesSteps = param.axesSteps;
|
|
54
|
-
const showIndex = param.showIndex;
|
|
55
|
-
const thickness = param.thickness;
|
|
56
|
-
const showSeriesCount = param.showSeriesCount;
|
|
57
|
-
|
|
58
|
-
let x;
|
|
59
|
-
let y;
|
|
60
|
-
|
|
61
|
-
const minmaxX = axesSteps.x[this.xAxisIndex];
|
|
62
|
-
const minmaxY = axesSteps.y[this.yAxisIndex];
|
|
63
|
-
|
|
64
|
-
const xArea = chartRect.chartWidth - (labelOffset.left + labelOffset.right);
|
|
65
|
-
const yArea = chartRect.chartHeight - (labelOffset.top + labelOffset.bottom);
|
|
66
|
-
const xsp = chartRect.x1 + labelOffset.left;
|
|
67
|
-
const ysp = chartRect.y2 - labelOffset.bottom;
|
|
68
|
-
|
|
69
|
-
const dArea = isHorizontal ? yArea : xArea;
|
|
70
|
-
const cArea = dArea / (this.data.length || 1);
|
|
71
|
-
|
|
72
|
-
let cPad;
|
|
73
|
-
const isUnableToDrawCategoryPadding = param.cPadRatio >= 1 || param.cPadRatio <= 0;
|
|
74
|
-
if (isUnableToDrawCategoryPadding) {
|
|
75
|
-
cPad = 2;
|
|
76
|
-
} else {
|
|
77
|
-
cPad = Math.max((dArea * (param.cPadRatio / 2)) / this.data.length, 2);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
let bArea;
|
|
81
|
-
let w;
|
|
82
|
-
let h;
|
|
83
|
-
|
|
84
|
-
bArea = cArea > (cPad * 2) ? (cArea - (cPad * 2)) : cArea;
|
|
85
|
-
bArea = this.isExistGrp ? bArea : bArea / showSeriesCount;
|
|
86
|
-
|
|
87
|
-
const size = Math.ceil(bArea * thickness);
|
|
88
|
-
|
|
89
|
-
w = isHorizontal ? null : size;
|
|
90
|
-
h = isHorizontal ? size : null;
|
|
91
|
-
|
|
92
|
-
const bPad = isHorizontal ? (bArea - h) / 2 : (bArea - w) / 2;
|
|
93
|
-
const barSeriesX = this.isExistGrp ? 1 : showIndex + 1;
|
|
94
|
-
|
|
95
|
-
this.size.cat = cArea;
|
|
96
|
-
this.size.bar = bArea;
|
|
97
|
-
this.size.cPad = cPad;
|
|
98
|
-
this.size.bPad = bPad;
|
|
99
|
-
this.size.w = w;
|
|
100
|
-
this.size.h = h;
|
|
101
|
-
this.size.ix = barSeriesX;
|
|
102
|
-
this.chartRect = chartRect;
|
|
103
|
-
this.labelOffset = labelOffset;
|
|
104
|
-
this.borderRadius = param.borderRadius;
|
|
105
|
-
|
|
106
|
-
let categoryPoint = null;
|
|
107
|
-
|
|
108
|
-
this.data.forEach((dataItem, index) => {
|
|
109
|
-
ctx.beginPath();
|
|
110
|
-
|
|
111
|
-
const item = dataItem;
|
|
112
|
-
|
|
113
|
-
if (isHorizontal) {
|
|
114
|
-
categoryPoint = ysp - (cArea * index) - cPad;
|
|
115
|
-
} else {
|
|
116
|
-
categoryPoint = xsp + (cArea * index) + cPad;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (isHorizontal) {
|
|
120
|
-
x = xsp;
|
|
121
|
-
y = Math.round(categoryPoint - ((bArea * barSeriesX) - (h + bPad)));
|
|
122
|
-
} else {
|
|
123
|
-
x = Math.round(categoryPoint + ((bArea * barSeriesX) - (w + bPad)));
|
|
124
|
-
y = ysp;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (isHorizontal) {
|
|
128
|
-
if (item.b) {
|
|
129
|
-
w = Canvas.calculateX(item.x - item.b, minmaxX.graphMin, minmaxX.graphMax, xArea);
|
|
130
|
-
x = Canvas.calculateX(item.b, minmaxX.graphMin, minmaxX.graphMax, xArea, xsp);
|
|
131
|
-
} else {
|
|
132
|
-
w = Canvas.calculateX(item.x, minmaxX.graphMin, minmaxX.graphMax, xArea);
|
|
133
|
-
}
|
|
134
|
-
} else if (item.b) { // vertical stack bar chart
|
|
135
|
-
h = Canvas.calculateY(item.y - item.b, minmaxY.graphMin, minmaxY.graphMax, yArea);
|
|
136
|
-
y = Canvas.calculateY(item.b, minmaxY.graphMin, minmaxY.graphMax, yArea, ysp);
|
|
137
|
-
} else { // vertical bar chart
|
|
138
|
-
h = Canvas.calculateY(item.y, minmaxY.graphMin, minmaxY.graphMax, yArea);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const barColor = item.dataColor || this.color;
|
|
142
|
-
|
|
143
|
-
const legendHitInfo = param?.legendHitInfo;
|
|
144
|
-
const selectLabelOption = param?.selectLabel?.option;
|
|
145
|
-
const selectedLabelList = param?.selectLabel?.selected?.dataIndex ?? [];
|
|
146
|
-
let isDownplay = false;
|
|
147
|
-
|
|
148
|
-
if (legendHitInfo) {
|
|
149
|
-
isDownplay = legendHitInfo?.sId !== this.sId;
|
|
150
|
-
} else if (selectLabelOption?.use && selectLabelOption?.useSeriesOpacity) {
|
|
151
|
-
isDownplay = selectedLabelList.length && !selectedLabelList.includes(index);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (typeof barColor !== 'string') {
|
|
155
|
-
ctx.fillStyle = Canvas.createGradient(
|
|
156
|
-
ctx,
|
|
157
|
-
isHorizontal,
|
|
158
|
-
{ x, y, w, h },
|
|
159
|
-
barColor,
|
|
160
|
-
isDownplay,
|
|
161
|
-
);
|
|
162
|
-
} else {
|
|
163
|
-
const noneDownplayOpacity = barColor.includes('rgba') ? Util.getOpacity(barColor) : 1;
|
|
164
|
-
const opacity = isDownplay ? 0.1 : noneDownplayOpacity;
|
|
165
|
-
|
|
166
|
-
ctx.fillStyle = Util.colorStringToRgba(barColor, opacity);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
this.drawBar({
|
|
170
|
-
ctx,
|
|
171
|
-
positions: { x, y, w, h },
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
if (showValue.use) {
|
|
175
|
-
this.drawValueLabels({
|
|
176
|
-
context: ctx,
|
|
177
|
-
data: item,
|
|
178
|
-
positions: {
|
|
179
|
-
x,
|
|
180
|
-
y,
|
|
181
|
-
h,
|
|
182
|
-
w,
|
|
183
|
-
},
|
|
184
|
-
isHighlight: false,
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
item.xp = x; // eslint-disable-line
|
|
189
|
-
item.yp = y; // eslint-disable-line
|
|
190
|
-
item.w = w; // eslint-disable-line
|
|
191
|
-
item.h = isHorizontal ? -h : h; // eslint-disable-line
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Draw item highlight
|
|
197
|
-
* @param {object} item object for drawing series data
|
|
198
|
-
* @param {CanvasRenderingContext2D} context canvas context
|
|
199
|
-
*
|
|
200
|
-
* @returns {undefined}
|
|
201
|
-
*/
|
|
202
|
-
itemHighlight(item, context) {
|
|
203
|
-
const showValue = this.showValue;
|
|
204
|
-
|
|
205
|
-
const gdata = item.data;
|
|
206
|
-
const ctx = context;
|
|
207
|
-
|
|
208
|
-
const x = gdata.xp;
|
|
209
|
-
const y = gdata.yp;
|
|
210
|
-
const w = gdata.w;
|
|
211
|
-
const h = gdata.h;
|
|
212
|
-
|
|
213
|
-
ctx.save();
|
|
214
|
-
ctx.shadowOffsetX = 0;
|
|
215
|
-
ctx.shadowOffsetY = 0;
|
|
216
|
-
ctx.shadowBlur = 4;
|
|
217
|
-
|
|
218
|
-
const color = item.data.dataColor || this.color;
|
|
219
|
-
if (typeof color !== 'string') {
|
|
220
|
-
const grd = Canvas.createGradient(ctx, this.isHorizontal, { x, y, w, h }, color);
|
|
221
|
-
ctx.fillStyle = grd;
|
|
222
|
-
ctx.shadowColor = color[color.length - 1][1];
|
|
223
|
-
} else {
|
|
224
|
-
ctx.fillStyle = color;
|
|
225
|
-
ctx.shadowColor = color;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
ctx.beginPath();
|
|
229
|
-
|
|
230
|
-
this.drawBar({
|
|
231
|
-
ctx,
|
|
232
|
-
positions: { x, y, w, h: this.isHorizontal ? -h : h },
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
if (showValue.use) {
|
|
236
|
-
this.drawValueLabels({
|
|
237
|
-
context: ctx,
|
|
238
|
-
data: gdata,
|
|
239
|
-
positions: {
|
|
240
|
-
x,
|
|
241
|
-
y,
|
|
242
|
-
h,
|
|
243
|
-
w,
|
|
244
|
-
},
|
|
245
|
-
isHighlight: true,
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
ctx.restore();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Find graph item
|
|
254
|
-
* @param {array} offset mouse position
|
|
255
|
-
* @param {boolean} isHorizontal determines if a horizontal option's value
|
|
256
|
-
*
|
|
257
|
-
* @returns {object} graph item
|
|
258
|
-
*/
|
|
259
|
-
findGraphData(offset, isHorizontal) {
|
|
260
|
-
return isHorizontal ? this.findGraphRangeCount(offset) : this.findGraphRange(offset);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Find graph item
|
|
265
|
-
* @param {array} offset mouse position
|
|
266
|
-
*
|
|
267
|
-
* @returns {object} graph item
|
|
268
|
-
*/
|
|
269
|
-
findGraphRange(offset) {
|
|
270
|
-
const xp = offset[0];
|
|
271
|
-
const yp = offset[1];
|
|
272
|
-
const item = { data: null, hit: false, color: this.color };
|
|
273
|
-
const gdata = this.data;
|
|
274
|
-
|
|
275
|
-
let s = 0;
|
|
276
|
-
let e = gdata.length - 1;
|
|
277
|
-
|
|
278
|
-
while (s <= e) {
|
|
279
|
-
const m = Math.floor((s + e) / 2);
|
|
280
|
-
const sx = gdata[m].xp;
|
|
281
|
-
const sy = gdata[m].yp;
|
|
282
|
-
const ex = sx + gdata[m].w;
|
|
283
|
-
const ey = sy + gdata[m].h;
|
|
284
|
-
|
|
285
|
-
if ((sx <= xp) && (xp <= ex)) {
|
|
286
|
-
item.data = gdata[m];
|
|
287
|
-
item.index = m;
|
|
288
|
-
|
|
289
|
-
if ((ey <= yp) && (yp <= sy)) {
|
|
290
|
-
item.hit = true;
|
|
291
|
-
}
|
|
292
|
-
return item;
|
|
293
|
-
} else if (sx + 4 < xp) {
|
|
294
|
-
s = m + 1;
|
|
295
|
-
} else {
|
|
296
|
-
e = m - 1;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return item;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Find graph item (horizontal)
|
|
305
|
-
* @param {array} offset mouse position
|
|
306
|
-
*
|
|
307
|
-
* @returns {object} graph item
|
|
308
|
-
*/
|
|
309
|
-
findGraphRangeCount(offset) {
|
|
310
|
-
const xp = offset[0];
|
|
311
|
-
const yp = offset[1];
|
|
312
|
-
const item = { data: null, hit: false, color: this.color };
|
|
313
|
-
const gdata = this.data;
|
|
314
|
-
|
|
315
|
-
let s = 0;
|
|
316
|
-
let e = gdata.length - 1;
|
|
317
|
-
|
|
318
|
-
while (s <= e) {
|
|
319
|
-
const m = Math.floor((s + e) / 2);
|
|
320
|
-
const sx = gdata[m].xp;
|
|
321
|
-
const sy = gdata[m].yp;
|
|
322
|
-
const ex = sx + gdata[m].w;
|
|
323
|
-
const ey = sy + gdata[m].h;
|
|
324
|
-
|
|
325
|
-
if ((ey <= yp) && (yp <= sy)) {
|
|
326
|
-
item.data = gdata[m];
|
|
327
|
-
item.index = m;
|
|
328
|
-
|
|
329
|
-
if ((sx <= xp) && (xp <= ex)) {
|
|
330
|
-
item.hit = true;
|
|
331
|
-
}
|
|
332
|
-
return item;
|
|
333
|
-
} else if (ey < yp) {
|
|
334
|
-
e = m - 1;
|
|
335
|
-
} else {
|
|
336
|
-
s = m + 1;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
return item;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* Draw value label if series 'use' of showValue option is true
|
|
345
|
-
*
|
|
346
|
-
* @param context canvas context
|
|
347
|
-
* @param data series value data (model.store.js addData return value)
|
|
348
|
-
* @param positions series value positions
|
|
349
|
-
* @param isHighlight draw label with highlight effect
|
|
350
|
-
*/
|
|
351
|
-
drawValueLabels({ context, data, positions, isHighlight }) {
|
|
352
|
-
const isHorizontal = this.isHorizontal;
|
|
353
|
-
const { fontSize, textColor, align, formatter, decimalPoint } = this.showValue;
|
|
354
|
-
const { x, y, w, h } = positions;
|
|
355
|
-
const ctx = context;
|
|
356
|
-
|
|
357
|
-
ctx.save();
|
|
358
|
-
ctx.beginPath();
|
|
359
|
-
|
|
360
|
-
ctx.font = `normal normal normal ${fontSize}px Roboto`;
|
|
361
|
-
ctx.fillStyle = textColor;
|
|
362
|
-
ctx.lineWidth = 1;
|
|
363
|
-
ctx.textBaseline = 'middle';
|
|
364
|
-
ctx.textAlign = isHorizontal && align !== 'center' ? 'left' : 'center';
|
|
365
|
-
|
|
366
|
-
let value;
|
|
367
|
-
const isStacked = truthy(this.stackIndex);
|
|
368
|
-
if (isStacked) {
|
|
369
|
-
value = data.o;
|
|
370
|
-
} else {
|
|
371
|
-
value = (isHorizontal ? data.x : data.y) ?? '';
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
let formattedTxt;
|
|
375
|
-
if (formatter) {
|
|
376
|
-
formattedTxt = formatter(value);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
if (!formatter || typeof formattedTxt !== 'string') {
|
|
380
|
-
formattedTxt = Util.labelSignFormat(value, decimalPoint) ?? '';
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
const textWidth = Math.round(ctx.measureText(formattedTxt).width);
|
|
384
|
-
const textHeight = fontSize + 4;
|
|
385
|
-
const minXPos = x + 10;
|
|
386
|
-
const minYPos = y - 10;
|
|
387
|
-
const widthFreeSpaceToDraw = w - 10;
|
|
388
|
-
const heightFreeSpaceToDraw = Math.abs(h + 10);
|
|
389
|
-
const centerX = x + (w / 2) <= minXPos ? minXPos : x + (w / 2);
|
|
390
|
-
const centerY = y + (h / 2) >= minYPos ? minYPos : y + (h / 2);
|
|
391
|
-
const centerYHorizontal = isHighlight ? y + (h / 2) : y - (h / 2);
|
|
392
|
-
|
|
393
|
-
switch (align) {
|
|
394
|
-
case 'start': {
|
|
395
|
-
if (isHorizontal) {
|
|
396
|
-
if (textWidth < widthFreeSpaceToDraw) {
|
|
397
|
-
ctx.fillText(formattedTxt, minXPos, centerYHorizontal);
|
|
398
|
-
}
|
|
399
|
-
} else if (textHeight < heightFreeSpaceToDraw) {
|
|
400
|
-
ctx.fillText(formattedTxt, centerX, minYPos);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
break;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
case 'center': {
|
|
407
|
-
if (isHorizontal) {
|
|
408
|
-
if (textWidth < widthFreeSpaceToDraw) {
|
|
409
|
-
ctx.fillText(formattedTxt, centerX, centerYHorizontal);
|
|
410
|
-
}
|
|
411
|
-
} else if (textHeight < heightFreeSpaceToDraw) {
|
|
412
|
-
ctx.fillText(formattedTxt, centerX, centerY);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
break;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
case 'out': {
|
|
419
|
-
if (isStacked) {
|
|
420
|
-
console.warn('[EVUI][Bar Chart] In case of Stack Bar Chart, \'out\' of \'showValue\'\'s align is not supported.');
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
if (isHorizontal) {
|
|
425
|
-
ctx.fillText(formattedTxt, minXPos + w, centerYHorizontal);
|
|
426
|
-
} else {
|
|
427
|
-
ctx.fillText(formattedTxt, centerX, y + h - (textHeight / 2));
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
break;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
default:
|
|
434
|
-
case 'end': {
|
|
435
|
-
if (isHorizontal) {
|
|
436
|
-
if (textWidth < widthFreeSpaceToDraw) {
|
|
437
|
-
const xPos = x + w - (textWidth * 2);
|
|
438
|
-
ctx.fillText(formattedTxt, xPos <= minXPos ? minXPos : xPos, centerYHorizontal);
|
|
439
|
-
}
|
|
440
|
-
} else if (textHeight < heightFreeSpaceToDraw) {
|
|
441
|
-
const yPos = y + h + textHeight;
|
|
442
|
-
ctx.fillText(formattedTxt, centerX, yPos >= minYPos ? minYPos : yPos);
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
break;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
ctx.restore();
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
drawBar({ ctx, positions }) {
|
|
453
|
-
const isHorizontal = this.isHorizontal;
|
|
454
|
-
const isStackBar = 'stackIndex' in this;
|
|
455
|
-
const isBorderRadius = this.borderRadius && this.borderRadius > 0;
|
|
456
|
-
const { x, y, w } = positions;
|
|
457
|
-
const h = isHorizontal ? -positions.h : positions.h;
|
|
458
|
-
|
|
459
|
-
// Dont's draw bar that has value 0
|
|
460
|
-
if (w === 0 || h === 0) {
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
if (isBorderRadius && !isStackBar) {
|
|
465
|
-
try {
|
|
466
|
-
this.drawRoundedRect(ctx, positions);
|
|
467
|
-
} catch (e) {
|
|
468
|
-
ctx.fillRect(x, y, w, h);
|
|
469
|
-
}
|
|
470
|
-
} else {
|
|
471
|
-
ctx.fillRect(x, y, w, h);
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
drawRoundedRect(ctx, positions) {
|
|
476
|
-
const chartRect = this.chartRect;
|
|
477
|
-
const labelOffset = this.labelOffset;
|
|
478
|
-
const isHorizontal = this.isHorizontal;
|
|
479
|
-
const { x, y } = positions;
|
|
480
|
-
let { w, h } = positions;
|
|
481
|
-
let r = this.borderRadius;
|
|
482
|
-
|
|
483
|
-
const squarePath = new Path2D();
|
|
484
|
-
squarePath.rect(
|
|
485
|
-
chartRect.x1 + labelOffset.left,
|
|
486
|
-
chartRect.y1,
|
|
487
|
-
chartRect.chartWidth - labelOffset.right,
|
|
488
|
-
chartRect.chartHeight - labelOffset.bottom,
|
|
489
|
-
);
|
|
490
|
-
|
|
491
|
-
ctx.clip(squarePath);
|
|
492
|
-
|
|
493
|
-
ctx.moveTo(x, y);
|
|
494
|
-
|
|
495
|
-
if (isHorizontal) {
|
|
496
|
-
if (h < r * 2) {
|
|
497
|
-
r = h / 2;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
w -= r;
|
|
501
|
-
ctx.lineTo(x + w, y);
|
|
502
|
-
ctx.arcTo(x + w + r, y, x + w + r, y - r, r);
|
|
503
|
-
ctx.arcTo(x + w + r, y - h, x + w, y - h, r);
|
|
504
|
-
ctx.lineTo(x, y - h);
|
|
505
|
-
ctx.lineTo(x, y);
|
|
506
|
-
} else {
|
|
507
|
-
if (w < r * 2) {
|
|
508
|
-
r = w / 2;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
h += r;
|
|
512
|
-
ctx.lineTo(x + w, y);
|
|
513
|
-
ctx.lineTo(x + w, y + h);
|
|
514
|
-
ctx.arcTo(x + w, y + h - r, x + w - r, y + h - r, r);
|
|
515
|
-
ctx.arcTo(x, y + h - r, x, y + h, r);
|
|
516
|
-
ctx.lineTo(x, y);
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
ctx.fill();
|
|
520
|
-
ctx.closePath();
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
export default Bar;
|
|
1
|
+
import { defaultsDeep } from 'lodash-es';
|
|
2
|
+
import { truthy } from '@/common/utils';
|
|
3
|
+
import { COLOR, BAR_OPTION } from '../helpers/helpers.constant';
|
|
4
|
+
import Canvas from '../helpers/helpers.canvas';
|
|
5
|
+
import Util from '../helpers/helpers.util';
|
|
6
|
+
|
|
7
|
+
class Bar {
|
|
8
|
+
constructor(sId, opt, sIdx, isHorizontal) {
|
|
9
|
+
const merged = defaultsDeep({}, opt, BAR_OPTION);
|
|
10
|
+
Object.keys(merged).forEach((key) => {
|
|
11
|
+
this[key] = merged[key];
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
if (this.name === undefined) {
|
|
15
|
+
this.name = `series-${sIdx}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (this.color === undefined) {
|
|
19
|
+
this.color = COLOR[sIdx];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this.type = 'bar';
|
|
23
|
+
this.sId = sId;
|
|
24
|
+
this.data = [];
|
|
25
|
+
this.isHorizontal = isHorizontal;
|
|
26
|
+
this.size = {
|
|
27
|
+
cat: 0,
|
|
28
|
+
bar: 0,
|
|
29
|
+
cPad: 0,
|
|
30
|
+
bPad: 0,
|
|
31
|
+
w: 0,
|
|
32
|
+
h: 0,
|
|
33
|
+
ix: 0,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Draw series data
|
|
39
|
+
* @param {object} param object for drawing series data
|
|
40
|
+
*
|
|
41
|
+
* @returns {undefined}
|
|
42
|
+
*/
|
|
43
|
+
draw(param) {
|
|
44
|
+
if (!this.show) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const { isHorizontal, showValue } = this;
|
|
49
|
+
|
|
50
|
+
const ctx = param.ctx;
|
|
51
|
+
const chartRect = param.chartRect;
|
|
52
|
+
const labelOffset = param.labelOffset;
|
|
53
|
+
const axesSteps = param.axesSteps;
|
|
54
|
+
const showIndex = param.showIndex;
|
|
55
|
+
const thickness = param.thickness;
|
|
56
|
+
const showSeriesCount = param.showSeriesCount;
|
|
57
|
+
|
|
58
|
+
let x;
|
|
59
|
+
let y;
|
|
60
|
+
|
|
61
|
+
const minmaxX = axesSteps.x[this.xAxisIndex];
|
|
62
|
+
const minmaxY = axesSteps.y[this.yAxisIndex];
|
|
63
|
+
|
|
64
|
+
const xArea = chartRect.chartWidth - (labelOffset.left + labelOffset.right);
|
|
65
|
+
const yArea = chartRect.chartHeight - (labelOffset.top + labelOffset.bottom);
|
|
66
|
+
const xsp = chartRect.x1 + labelOffset.left;
|
|
67
|
+
const ysp = chartRect.y2 - labelOffset.bottom;
|
|
68
|
+
|
|
69
|
+
const dArea = isHorizontal ? yArea : xArea;
|
|
70
|
+
const cArea = dArea / (this.data.length || 1);
|
|
71
|
+
|
|
72
|
+
let cPad;
|
|
73
|
+
const isUnableToDrawCategoryPadding = param.cPadRatio >= 1 || param.cPadRatio <= 0;
|
|
74
|
+
if (isUnableToDrawCategoryPadding) {
|
|
75
|
+
cPad = 2;
|
|
76
|
+
} else {
|
|
77
|
+
cPad = Math.max((dArea * (param.cPadRatio / 2)) / this.data.length, 2);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let bArea;
|
|
81
|
+
let w;
|
|
82
|
+
let h;
|
|
83
|
+
|
|
84
|
+
bArea = cArea > (cPad * 2) ? (cArea - (cPad * 2)) : cArea;
|
|
85
|
+
bArea = this.isExistGrp ? bArea : bArea / showSeriesCount;
|
|
86
|
+
|
|
87
|
+
const size = Math.ceil(bArea * thickness);
|
|
88
|
+
|
|
89
|
+
w = isHorizontal ? null : size;
|
|
90
|
+
h = isHorizontal ? size : null;
|
|
91
|
+
|
|
92
|
+
const bPad = isHorizontal ? (bArea - h) / 2 : (bArea - w) / 2;
|
|
93
|
+
const barSeriesX = this.isExistGrp ? 1 : showIndex + 1;
|
|
94
|
+
|
|
95
|
+
this.size.cat = cArea;
|
|
96
|
+
this.size.bar = bArea;
|
|
97
|
+
this.size.cPad = cPad;
|
|
98
|
+
this.size.bPad = bPad;
|
|
99
|
+
this.size.w = w;
|
|
100
|
+
this.size.h = h;
|
|
101
|
+
this.size.ix = barSeriesX;
|
|
102
|
+
this.chartRect = chartRect;
|
|
103
|
+
this.labelOffset = labelOffset;
|
|
104
|
+
this.borderRadius = param.borderRadius;
|
|
105
|
+
|
|
106
|
+
let categoryPoint = null;
|
|
107
|
+
|
|
108
|
+
this.data.forEach((dataItem, index) => {
|
|
109
|
+
ctx.beginPath();
|
|
110
|
+
|
|
111
|
+
const item = dataItem;
|
|
112
|
+
|
|
113
|
+
if (isHorizontal) {
|
|
114
|
+
categoryPoint = ysp - (cArea * index) - cPad;
|
|
115
|
+
} else {
|
|
116
|
+
categoryPoint = xsp + (cArea * index) + cPad;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (isHorizontal) {
|
|
120
|
+
x = xsp;
|
|
121
|
+
y = Math.round(categoryPoint - ((bArea * barSeriesX) - (h + bPad)));
|
|
122
|
+
} else {
|
|
123
|
+
x = Math.round(categoryPoint + ((bArea * barSeriesX) - (w + bPad)));
|
|
124
|
+
y = ysp;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (isHorizontal) {
|
|
128
|
+
if (item.b) {
|
|
129
|
+
w = Canvas.calculateX(item.x - item.b, minmaxX.graphMin, minmaxX.graphMax, xArea);
|
|
130
|
+
x = Canvas.calculateX(item.b, minmaxX.graphMin, minmaxX.graphMax, xArea, xsp);
|
|
131
|
+
} else {
|
|
132
|
+
w = Canvas.calculateX(item.x, minmaxX.graphMin, minmaxX.graphMax, xArea);
|
|
133
|
+
}
|
|
134
|
+
} else if (item.b) { // vertical stack bar chart
|
|
135
|
+
h = Canvas.calculateY(item.y - item.b, minmaxY.graphMin, minmaxY.graphMax, yArea);
|
|
136
|
+
y = Canvas.calculateY(item.b, minmaxY.graphMin, minmaxY.graphMax, yArea, ysp);
|
|
137
|
+
} else { // vertical bar chart
|
|
138
|
+
h = Canvas.calculateY(item.y, minmaxY.graphMin, minmaxY.graphMax, yArea);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const barColor = item.dataColor || this.color;
|
|
142
|
+
|
|
143
|
+
const legendHitInfo = param?.legendHitInfo;
|
|
144
|
+
const selectLabelOption = param?.selectLabel?.option;
|
|
145
|
+
const selectedLabelList = param?.selectLabel?.selected?.dataIndex ?? [];
|
|
146
|
+
let isDownplay = false;
|
|
147
|
+
|
|
148
|
+
if (legendHitInfo) {
|
|
149
|
+
isDownplay = legendHitInfo?.sId !== this.sId;
|
|
150
|
+
} else if (selectLabelOption?.use && selectLabelOption?.useSeriesOpacity) {
|
|
151
|
+
isDownplay = selectedLabelList.length && !selectedLabelList.includes(index);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (typeof barColor !== 'string') {
|
|
155
|
+
ctx.fillStyle = Canvas.createGradient(
|
|
156
|
+
ctx,
|
|
157
|
+
isHorizontal,
|
|
158
|
+
{ x, y, w, h },
|
|
159
|
+
barColor,
|
|
160
|
+
isDownplay,
|
|
161
|
+
);
|
|
162
|
+
} else {
|
|
163
|
+
const noneDownplayOpacity = barColor.includes('rgba') ? Util.getOpacity(barColor) : 1;
|
|
164
|
+
const opacity = isDownplay ? 0.1 : noneDownplayOpacity;
|
|
165
|
+
|
|
166
|
+
ctx.fillStyle = Util.colorStringToRgba(barColor, opacity);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
this.drawBar({
|
|
170
|
+
ctx,
|
|
171
|
+
positions: { x, y, w, h },
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
if (showValue.use) {
|
|
175
|
+
this.drawValueLabels({
|
|
176
|
+
context: ctx,
|
|
177
|
+
data: item,
|
|
178
|
+
positions: {
|
|
179
|
+
x,
|
|
180
|
+
y,
|
|
181
|
+
h,
|
|
182
|
+
w,
|
|
183
|
+
},
|
|
184
|
+
isHighlight: false,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
item.xp = x; // eslint-disable-line
|
|
189
|
+
item.yp = y; // eslint-disable-line
|
|
190
|
+
item.w = w; // eslint-disable-line
|
|
191
|
+
item.h = isHorizontal ? -h : h; // eslint-disable-line
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Draw item highlight
|
|
197
|
+
* @param {object} item object for drawing series data
|
|
198
|
+
* @param {CanvasRenderingContext2D} context canvas context
|
|
199
|
+
*
|
|
200
|
+
* @returns {undefined}
|
|
201
|
+
*/
|
|
202
|
+
itemHighlight(item, context) {
|
|
203
|
+
const showValue = this.showValue;
|
|
204
|
+
|
|
205
|
+
const gdata = item.data;
|
|
206
|
+
const ctx = context;
|
|
207
|
+
|
|
208
|
+
const x = gdata.xp;
|
|
209
|
+
const y = gdata.yp;
|
|
210
|
+
const w = gdata.w;
|
|
211
|
+
const h = gdata.h;
|
|
212
|
+
|
|
213
|
+
ctx.save();
|
|
214
|
+
ctx.shadowOffsetX = 0;
|
|
215
|
+
ctx.shadowOffsetY = 0;
|
|
216
|
+
ctx.shadowBlur = 4;
|
|
217
|
+
|
|
218
|
+
const color = item.data.dataColor || this.color;
|
|
219
|
+
if (typeof color !== 'string') {
|
|
220
|
+
const grd = Canvas.createGradient(ctx, this.isHorizontal, { x, y, w, h }, color);
|
|
221
|
+
ctx.fillStyle = grd;
|
|
222
|
+
ctx.shadowColor = color[color.length - 1][1];
|
|
223
|
+
} else {
|
|
224
|
+
ctx.fillStyle = color;
|
|
225
|
+
ctx.shadowColor = color;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
ctx.beginPath();
|
|
229
|
+
|
|
230
|
+
this.drawBar({
|
|
231
|
+
ctx,
|
|
232
|
+
positions: { x, y, w, h: this.isHorizontal ? -h : h },
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
if (showValue.use) {
|
|
236
|
+
this.drawValueLabels({
|
|
237
|
+
context: ctx,
|
|
238
|
+
data: gdata,
|
|
239
|
+
positions: {
|
|
240
|
+
x,
|
|
241
|
+
y,
|
|
242
|
+
h,
|
|
243
|
+
w,
|
|
244
|
+
},
|
|
245
|
+
isHighlight: true,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
ctx.restore();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Find graph item
|
|
254
|
+
* @param {array} offset mouse position
|
|
255
|
+
* @param {boolean} isHorizontal determines if a horizontal option's value
|
|
256
|
+
*
|
|
257
|
+
* @returns {object} graph item
|
|
258
|
+
*/
|
|
259
|
+
findGraphData(offset, isHorizontal) {
|
|
260
|
+
return isHorizontal ? this.findGraphRangeCount(offset) : this.findGraphRange(offset);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Find graph item
|
|
265
|
+
* @param {array} offset mouse position
|
|
266
|
+
*
|
|
267
|
+
* @returns {object} graph item
|
|
268
|
+
*/
|
|
269
|
+
findGraphRange(offset) {
|
|
270
|
+
const xp = offset[0];
|
|
271
|
+
const yp = offset[1];
|
|
272
|
+
const item = { data: null, hit: false, color: this.color };
|
|
273
|
+
const gdata = this.data;
|
|
274
|
+
|
|
275
|
+
let s = 0;
|
|
276
|
+
let e = gdata.length - 1;
|
|
277
|
+
|
|
278
|
+
while (s <= e) {
|
|
279
|
+
const m = Math.floor((s + e) / 2);
|
|
280
|
+
const sx = gdata[m].xp;
|
|
281
|
+
const sy = gdata[m].yp;
|
|
282
|
+
const ex = sx + gdata[m].w;
|
|
283
|
+
const ey = sy + gdata[m].h;
|
|
284
|
+
|
|
285
|
+
if ((sx <= xp) && (xp <= ex)) {
|
|
286
|
+
item.data = gdata[m];
|
|
287
|
+
item.index = m;
|
|
288
|
+
|
|
289
|
+
if ((ey <= yp) && (yp <= sy)) {
|
|
290
|
+
item.hit = true;
|
|
291
|
+
}
|
|
292
|
+
return item;
|
|
293
|
+
} else if (sx + 4 < xp) {
|
|
294
|
+
s = m + 1;
|
|
295
|
+
} else {
|
|
296
|
+
e = m - 1;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return item;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Find graph item (horizontal)
|
|
305
|
+
* @param {array} offset mouse position
|
|
306
|
+
*
|
|
307
|
+
* @returns {object} graph item
|
|
308
|
+
*/
|
|
309
|
+
findGraphRangeCount(offset) {
|
|
310
|
+
const xp = offset[0];
|
|
311
|
+
const yp = offset[1];
|
|
312
|
+
const item = { data: null, hit: false, color: this.color };
|
|
313
|
+
const gdata = this.data;
|
|
314
|
+
|
|
315
|
+
let s = 0;
|
|
316
|
+
let e = gdata.length - 1;
|
|
317
|
+
|
|
318
|
+
while (s <= e) {
|
|
319
|
+
const m = Math.floor((s + e) / 2);
|
|
320
|
+
const sx = gdata[m].xp;
|
|
321
|
+
const sy = gdata[m].yp;
|
|
322
|
+
const ex = sx + gdata[m].w;
|
|
323
|
+
const ey = sy + gdata[m].h;
|
|
324
|
+
|
|
325
|
+
if ((ey <= yp) && (yp <= sy)) {
|
|
326
|
+
item.data = gdata[m];
|
|
327
|
+
item.index = m;
|
|
328
|
+
|
|
329
|
+
if ((sx <= xp) && (xp <= ex)) {
|
|
330
|
+
item.hit = true;
|
|
331
|
+
}
|
|
332
|
+
return item;
|
|
333
|
+
} else if (ey < yp) {
|
|
334
|
+
e = m - 1;
|
|
335
|
+
} else {
|
|
336
|
+
s = m + 1;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return item;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Draw value label if series 'use' of showValue option is true
|
|
345
|
+
*
|
|
346
|
+
* @param context canvas context
|
|
347
|
+
* @param data series value data (model.store.js addData return value)
|
|
348
|
+
* @param positions series value positions
|
|
349
|
+
* @param isHighlight draw label with highlight effect
|
|
350
|
+
*/
|
|
351
|
+
drawValueLabels({ context, data, positions, isHighlight }) {
|
|
352
|
+
const isHorizontal = this.isHorizontal;
|
|
353
|
+
const { fontSize, textColor, align, formatter, decimalPoint } = this.showValue;
|
|
354
|
+
const { x, y, w, h } = positions;
|
|
355
|
+
const ctx = context;
|
|
356
|
+
|
|
357
|
+
ctx.save();
|
|
358
|
+
ctx.beginPath();
|
|
359
|
+
|
|
360
|
+
ctx.font = `normal normal normal ${fontSize}px Roboto`;
|
|
361
|
+
ctx.fillStyle = textColor;
|
|
362
|
+
ctx.lineWidth = 1;
|
|
363
|
+
ctx.textBaseline = 'middle';
|
|
364
|
+
ctx.textAlign = isHorizontal && align !== 'center' ? 'left' : 'center';
|
|
365
|
+
|
|
366
|
+
let value;
|
|
367
|
+
const isStacked = truthy(this.stackIndex);
|
|
368
|
+
if (isStacked) {
|
|
369
|
+
value = data.o;
|
|
370
|
+
} else {
|
|
371
|
+
value = (isHorizontal ? data.x : data.y) ?? '';
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
let formattedTxt;
|
|
375
|
+
if (formatter) {
|
|
376
|
+
formattedTxt = formatter(value);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (!formatter || typeof formattedTxt !== 'string') {
|
|
380
|
+
formattedTxt = Util.labelSignFormat(value, decimalPoint) ?? '';
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const textWidth = Math.round(ctx.measureText(formattedTxt).width);
|
|
384
|
+
const textHeight = fontSize + 4;
|
|
385
|
+
const minXPos = x + 10;
|
|
386
|
+
const minYPos = y - 10;
|
|
387
|
+
const widthFreeSpaceToDraw = w - 10;
|
|
388
|
+
const heightFreeSpaceToDraw = Math.abs(h + 10);
|
|
389
|
+
const centerX = x + (w / 2) <= minXPos ? minXPos : x + (w / 2);
|
|
390
|
+
const centerY = y + (h / 2) >= minYPos ? minYPos : y + (h / 2);
|
|
391
|
+
const centerYHorizontal = isHighlight ? y + (h / 2) : y - (h / 2);
|
|
392
|
+
|
|
393
|
+
switch (align) {
|
|
394
|
+
case 'start': {
|
|
395
|
+
if (isHorizontal) {
|
|
396
|
+
if (textWidth < widthFreeSpaceToDraw) {
|
|
397
|
+
ctx.fillText(formattedTxt, minXPos, centerYHorizontal);
|
|
398
|
+
}
|
|
399
|
+
} else if (textHeight < heightFreeSpaceToDraw) {
|
|
400
|
+
ctx.fillText(formattedTxt, centerX, minYPos);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
case 'center': {
|
|
407
|
+
if (isHorizontal) {
|
|
408
|
+
if (textWidth < widthFreeSpaceToDraw) {
|
|
409
|
+
ctx.fillText(formattedTxt, centerX, centerYHorizontal);
|
|
410
|
+
}
|
|
411
|
+
} else if (textHeight < heightFreeSpaceToDraw) {
|
|
412
|
+
ctx.fillText(formattedTxt, centerX, centerY);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
case 'out': {
|
|
419
|
+
if (isStacked) {
|
|
420
|
+
console.warn('[EVUI][Bar Chart] In case of Stack Bar Chart, \'out\' of \'showValue\'\'s align is not supported.');
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (isHorizontal) {
|
|
425
|
+
ctx.fillText(formattedTxt, minXPos + w, centerYHorizontal);
|
|
426
|
+
} else {
|
|
427
|
+
ctx.fillText(formattedTxt, centerX, y + h - (textHeight / 2));
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
break;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
default:
|
|
434
|
+
case 'end': {
|
|
435
|
+
if (isHorizontal) {
|
|
436
|
+
if (textWidth < widthFreeSpaceToDraw) {
|
|
437
|
+
const xPos = x + w - (textWidth * 2);
|
|
438
|
+
ctx.fillText(formattedTxt, xPos <= minXPos ? minXPos : xPos, centerYHorizontal);
|
|
439
|
+
}
|
|
440
|
+
} else if (textHeight < heightFreeSpaceToDraw) {
|
|
441
|
+
const yPos = y + h + textHeight;
|
|
442
|
+
ctx.fillText(formattedTxt, centerX, yPos >= minYPos ? minYPos : yPos);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
ctx.restore();
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
drawBar({ ctx, positions }) {
|
|
453
|
+
const isHorizontal = this.isHorizontal;
|
|
454
|
+
const isStackBar = 'stackIndex' in this;
|
|
455
|
+
const isBorderRadius = this.borderRadius && this.borderRadius > 0;
|
|
456
|
+
const { x, y, w } = positions;
|
|
457
|
+
const h = isHorizontal ? -positions.h : positions.h;
|
|
458
|
+
|
|
459
|
+
// Dont's draw bar that has value 0
|
|
460
|
+
if (w === 0 || h === 0) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if (isBorderRadius && !isStackBar) {
|
|
465
|
+
try {
|
|
466
|
+
this.drawRoundedRect(ctx, positions);
|
|
467
|
+
} catch (e) {
|
|
468
|
+
ctx.fillRect(x, y, w, h);
|
|
469
|
+
}
|
|
470
|
+
} else {
|
|
471
|
+
ctx.fillRect(x, y, w, h);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
drawRoundedRect(ctx, positions) {
|
|
476
|
+
const chartRect = this.chartRect;
|
|
477
|
+
const labelOffset = this.labelOffset;
|
|
478
|
+
const isHorizontal = this.isHorizontal;
|
|
479
|
+
const { x, y } = positions;
|
|
480
|
+
let { w, h } = positions;
|
|
481
|
+
let r = this.borderRadius;
|
|
482
|
+
|
|
483
|
+
const squarePath = new Path2D();
|
|
484
|
+
squarePath.rect(
|
|
485
|
+
chartRect.x1 + labelOffset.left,
|
|
486
|
+
chartRect.y1,
|
|
487
|
+
chartRect.chartWidth - labelOffset.right,
|
|
488
|
+
chartRect.chartHeight - labelOffset.bottom,
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
ctx.clip(squarePath);
|
|
492
|
+
|
|
493
|
+
ctx.moveTo(x, y);
|
|
494
|
+
|
|
495
|
+
if (isHorizontal) {
|
|
496
|
+
if (h < r * 2) {
|
|
497
|
+
r = h / 2;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
w -= r;
|
|
501
|
+
ctx.lineTo(x + w, y);
|
|
502
|
+
ctx.arcTo(x + w + r, y, x + w + r, y - r, r);
|
|
503
|
+
ctx.arcTo(x + w + r, y - h, x + w, y - h, r);
|
|
504
|
+
ctx.lineTo(x, y - h);
|
|
505
|
+
ctx.lineTo(x, y);
|
|
506
|
+
} else {
|
|
507
|
+
if (w < r * 2) {
|
|
508
|
+
r = w / 2;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
h += r;
|
|
512
|
+
ctx.lineTo(x + w, y);
|
|
513
|
+
ctx.lineTo(x + w, y + h);
|
|
514
|
+
ctx.arcTo(x + w, y + h - r, x + w - r, y + h - r, r);
|
|
515
|
+
ctx.arcTo(x, y + h - r, x, y + h, r);
|
|
516
|
+
ctx.lineTo(x, y);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
ctx.fill();
|
|
520
|
+
ctx.closePath();
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
export default Bar;
|