evui 3.3.17 → 3.3.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evui",
3
- "version": "3.3.17",
3
+ "version": "3.3.20",
4
4
  "description": "A EXEM Library project",
5
5
  "author": "exem <dev_client@ex-em.com>",
6
6
  "license": "MIT",
@@ -8,6 +8,7 @@ import StepScale from './scale/scale.step';
8
8
  import TimeCategoryScale from './scale/scale.time.category';
9
9
  import Title from './plugins/plugins.title';
10
10
  import Legend from './plugins/plugins.legend';
11
+ import GradientLegend from './plugins/plugins.legend.gradient';
11
12
  import Interaction from './plugins/plugins.interaction';
12
13
  import Tooltip from './plugins/plugins.tooltip';
13
14
  import Pie from './plugins/plugins.pie';
@@ -23,6 +24,10 @@ class EvChart {
23
24
  Object.assign(this, Pie);
24
25
  Object.assign(this, Tip);
25
26
 
27
+ if (options.type === 'heatMap' && options.legend.type === 'gradient') {
28
+ Object.assign(this, GradientLegend);
29
+ }
30
+
26
31
  this.target = target;
27
32
  this.data = data;
28
33
  this.options = options;
@@ -163,6 +168,7 @@ class EvChart {
163
168
  maxTipOpt: { background: maxTip.background, color: maxTip.color },
164
169
  selectLabel: { option: selectLabel, selected: this.defaultSelectInfo },
165
170
  selectSeries: { option: selectSeries, selected: this.defaultSelectInfo },
171
+ overlayCtx: this.overlayCtx,
166
172
  };
167
173
 
168
174
  let showIndex = 0;
@@ -443,15 +449,31 @@ class EvChart {
443
449
  const { width, height } = this.getChartDOMRect();
444
450
 
445
451
  const padding = this.options.padding;
452
+ const xAxisTitleOpt = this.options.axesX?.[0]?.title;
453
+ const yAxisTitleOpt = this.options.axesY?.[0]?.title;
454
+ const titleMargin = 10;
455
+
456
+ let xAxisTitleHeight = 0;
457
+ if (xAxisTitleOpt?.use && xAxisTitleOpt?.text) {
458
+ const fontSize = isNaN(xAxisTitleOpt?.fontSize) ? 12 : xAxisTitleOpt?.fontSize;
459
+ xAxisTitleHeight = fontSize + titleMargin;
460
+ }
461
+
462
+ let yAxisTitleHeight = 0;
463
+ if (yAxisTitleOpt?.use && yAxisTitleOpt?.text) {
464
+ const fontSize = isNaN(yAxisTitleOpt?.fontSize) ? 12 : yAxisTitleOpt?.fontSize;
465
+ yAxisTitleHeight = fontSize + titleMargin;
466
+ }
467
+
446
468
  const horizontalPadding = padding.left + padding.right;
447
- const verticalPadding = padding.top + padding.bottom;
469
+ const verticalPadding = padding.top + padding.bottom + xAxisTitleHeight + yAxisTitleHeight;
448
470
  const chartWidth = width > horizontalPadding ? width - horizontalPadding : width;
449
471
  const chartHeight = height > verticalPadding ? height - verticalPadding : height;
450
472
 
451
473
  const x1 = padding.left;
452
474
  const x2 = Math.max(width - padding.right, x1 + 2);
453
- const y1 = padding.top;
454
- const y2 = Math.max(height - padding.bottom, y1 + 2);
475
+ const y1 = padding.top + yAxisTitleHeight;
476
+ const y2 = Math.max(height - padding.bottom - xAxisTitleHeight, y1 + 2);
455
477
 
456
478
  return {
457
479
  x1,
@@ -1,15 +1,17 @@
1
1
  import { merge } from 'lodash-es';
2
2
  import Util from '../helpers/helpers.util';
3
3
  import { HEAT_MAP_OPTION } from '../helpers/helpers.constant';
4
+ import { convertToPercent } from '../../../common/utils';
4
5
 
5
6
  class HeatMap {
6
- constructor(sId, opt, colorOpt) {
7
+ constructor(sId, opt, colorOpt, isGradient) {
7
8
  const merged = merge({}, HEAT_MAP_OPTION, opt);
8
9
  Object.keys(merged).forEach((key) => {
9
10
  this[key] = merged[key];
10
11
  });
11
12
 
12
- this.createColorAxis(colorOpt);
13
+ this.isGradient = isGradient;
14
+ this.createColorState(colorOpt);
13
15
 
14
16
  this.sId = sId;
15
17
  this.data = [];
@@ -27,41 +29,66 @@ class HeatMap {
27
29
  * @param colorOpt
28
30
  * @returns {*[]}
29
31
  */
30
- createColorAxis(colorOpt) {
31
- const colorAxis = [];
32
+ createColorState(colorOpt) {
33
+ const colorState = [];
34
+ const regex = /[^0-9]&[^,]/g;
32
35
  const { min, max, categoryCnt, error, stroke } = colorOpt;
33
36
 
34
- const minColor = min.includes('#') ? Util.hexToRgb(min) : min;
35
- const maxColor = max.includes('#') ? Util.hexToRgb(max) : max;
37
+ const minColor = min.includes('#') ? Util.hexToRgb(min) : min.replace(regex, '');
38
+ const maxColor = max.includes('#') ? Util.hexToRgb(max) : max.replace(regex, '');
36
39
 
37
40
  const [minR, minG, minB] = minColor.split(',');
38
41
  const [maxR, maxG, maxB] = maxColor.split(',');
39
42
 
40
- const unitR = Math.floor((minR - maxR) / (categoryCnt - 1));
41
- const unitG = Math.floor((minG - maxG) / (categoryCnt - 1));
42
- const unitB = Math.floor((minB - maxB) / (categoryCnt - 1));
43
-
44
- for (let ix = 0; ix < categoryCnt; ix++) {
45
- const r = +minR - (unitR * ix);
46
- const g = +minG - (unitG * ix);
47
- const b = +minB - (unitB * ix);
48
-
49
- colorAxis.push({
50
- id: `color#${ix}`,
51
- value: `rgb(${r},${g},${b})`,
52
- state: 'normal',
53
- show: true,
54
- });
43
+ if (this.isGradient) {
44
+ colorState.push({
45
+ minColor: { minR, minG, minB },
46
+ maxColor: { maxR, maxG, maxB },
47
+ categoryCnt,
48
+ start: 0,
49
+ end: 100,
50
+ selectedValue: null,
51
+ });
52
+ } else {
53
+ const unitR = Math.floor((minR - maxR) / (categoryCnt - 1));
54
+ const unitG = Math.floor((minG - maxG) / (categoryCnt - 1));
55
+ const unitB = Math.floor((minB - maxB) / (categoryCnt - 1));
56
+
57
+ for (let ix = 0; ix < categoryCnt; ix++) {
58
+ const r = +minR - (unitR * ix);
59
+ const g = +minG - (unitG * ix);
60
+ const b = +minB - (unitB * ix);
61
+
62
+ colorState.push({
63
+ id: `color#${ix}`,
64
+ color: `rgb(${r},${g},${b})`,
65
+ state: 'normal',
66
+ show: true,
67
+ });
68
+ }
55
69
  }
56
70
 
57
- this.colorAxis = colorAxis;
71
+ this.colorState = colorState;
58
72
  this.errorColor = error;
59
73
  this.stroke = stroke;
60
74
  }
61
75
 
62
- getColorIndex(value) {
76
+ getColorForGradient(value) {
77
+ const { minColor, maxColor } = this.colorState[0];
78
+
79
+ const { minR, minG, minB } = minColor;
80
+ const { maxR, maxG, maxB } = maxColor;
81
+
82
+ const r = +minR - Math.floor(((minR - maxR) * value) / 100);
83
+ const g = +minG - Math.floor(((minG - maxG) * value) / 100);
84
+ const b = +minB - Math.floor(((minB - maxB) * value) / 100);
85
+
86
+ return `rgb(${r},${g},${b})`;
87
+ }
88
+
89
+ getColorIndexForIcon(value) {
63
90
  const { existError, min, interval, decimalPoint } = this.valueOpt;
64
- const maxIndex = this.colorAxis.length - 1;
91
+ const maxIndex = this.colorState.length - 1;
65
92
  if (existError && value < 0) {
66
93
  return maxIndex;
67
94
  }
@@ -75,11 +102,52 @@ class HeatMap {
75
102
  return colorIndex;
76
103
  }
77
104
 
105
+ getItemInfo(value) {
106
+ const { min, max } = this.valueOpt;
107
+ const itemInfo = {
108
+ show: false,
109
+ opacity: 0,
110
+ dataColor: null,
111
+ id: null,
112
+ isHighlight: null,
113
+ };
114
+ if (this.isGradient) {
115
+ const ratio = convertToPercent(value - min, max - min);
116
+ const { start, end, selectedValue } = this.colorState[0];
117
+ if (value < 0 || (start <= ratio && ratio <= end)) {
118
+ itemInfo.show = true;
119
+ itemInfo.isHighlight = selectedValue !== null
120
+ && (Math.floor(value) === Math.floor(min + ((max - min) * (selectedValue / 100))));
121
+ itemInfo.opacity = 1;
122
+ itemInfo.dataColor = value < 0
123
+ ? this.errorColor : this.getColorForGradient(ratio);
124
+ }
125
+ } else {
126
+ const colorIndex = this.getColorIndexForIcon(value);
127
+ const { show, state, color, id } = this.colorState[colorIndex];
128
+ itemInfo.show = show;
129
+ itemInfo.opacity = state === 'downplay' ? 0.1 : 1;
130
+ itemInfo.dataColor = value < 0 ? this.errorColor : color;
131
+ itemInfo.id = id;
132
+ }
133
+ return itemInfo;
134
+ }
135
+
78
136
  drawItem(ctx, x, y, w, h) {
79
137
  ctx.beginPath();
80
138
  if (this.stroke.show) {
81
- ctx.strokeRect(x, y, w, h);
82
- ctx.fillRect(x, y, w, h);
139
+ const { radius } = this.stroke;
140
+ if (radius > 0) {
141
+ ctx.moveTo(x + radius, y);
142
+ ctx.arcTo(x + w, y, x + w, y + h, radius);
143
+ ctx.arcTo(x + w, y + h, x, y + h, radius);
144
+ ctx.arcTo(x, y + h, x, y, radius);
145
+ ctx.arcTo(x, y, x + w, y, radius);
146
+ ctx.fill();
147
+ } else {
148
+ ctx.strokeRect(x, y, w, h);
149
+ ctx.fillRect(x, y, w, h);
150
+ }
83
151
  } else {
84
152
  const aliasPixel = Util.aliasPixel(1);
85
153
  ctx.fillRect(
@@ -122,7 +190,7 @@ class HeatMap {
122
190
  return;
123
191
  }
124
192
 
125
- const { ctx, chartRect, labelOffset } = param;
193
+ const { ctx, chartRect, labelOffset, overlayCtx } = param;
126
194
 
127
195
  const xArea = chartRect.chartWidth - (labelOffset.left + labelOffset.right);
128
196
  const yArea = chartRect.chartHeight - (labelOffset.top + labelOffset.bottom);
@@ -142,11 +210,11 @@ class HeatMap {
142
210
 
143
211
  if (xp !== null && yp !== null
144
212
  && (value !== null && value !== undefined)) {
145
- const colorIndex = this.getColorIndex(value);
146
- const opacity = this.colorAxis[colorIndex].state === 'downplay' ? 0.1 : 1;
147
- item.dataColor = value < 0 ? this.errorColor : this.colorAxis[colorIndex].value;
148
- item.cId = this.colorAxis[colorIndex].id;
149
- if (this.colorAxis[colorIndex].show) {
213
+ const { show, opacity, dataColor, id, isHighlight } = this.getItemInfo(value);
214
+ item.dataColor = dataColor;
215
+ item.cId = id;
216
+ ctx.save();
217
+ if (show) {
150
218
  ctx.fillStyle = Util.colorStringToRgba(item.dataColor, opacity);
151
219
  if (this.stroke.show) {
152
220
  const { color, lineWidth, opacity: sOpacity } = this.stroke;
@@ -161,25 +229,25 @@ class HeatMap {
161
229
  h -= (lineWidth * 2);
162
230
  }
163
231
  this.drawItem(ctx, xp, yp, w, h);
232
+ ctx.restore();
233
+
234
+ item.xp = xp;
235
+ item.yp = yp;
236
+ item.w = w;
237
+ item.h = h;
164
238
 
165
239
  if (this.showValue.use) {
166
240
  this.drawValueLabels({
167
241
  context: ctx,
168
242
  data: item,
169
- positions: {
170
- x: xp,
171
- y: yp,
172
- w,
173
- h,
174
- },
175
243
  });
176
244
  }
245
+ if (isHighlight) {
246
+ this.itemHighlight({
247
+ data: item,
248
+ }, overlayCtx);
249
+ }
177
250
  }
178
-
179
- item.xp = xp;
180
- item.yp = yp;
181
- item.w = w;
182
- item.h = h;
183
251
  }
184
252
  });
185
253
  }
@@ -190,9 +258,9 @@ class HeatMap {
190
258
  * @param context canvas context
191
259
  * @param data series value data (model.store.js addData return value)
192
260
  */
193
- drawValueLabels({ context, data, positions }) {
261
+ drawValueLabels({ context, data }) {
194
262
  const { fontSize, textColor, align, formatter, decimalPoint } = this.showValue;
195
- const { x, y, w, h } = positions;
263
+ const { xp: x, yp: y, w, h, o: value } = data;
196
264
  const ctx = context;
197
265
 
198
266
  ctx.save();
@@ -204,8 +272,6 @@ class HeatMap {
204
272
  ctx.textBaseline = 'middle';
205
273
  ctx.textAlign = align !== 'center' ? 'left' : 'center';
206
274
 
207
- const value = data.o;
208
-
209
275
  let formattedTxt;
210
276
  if (formatter) {
211
277
  formattedTxt = formatter(value);
@@ -295,31 +361,36 @@ class HeatMap {
295
361
  const h = gdata.h;
296
362
  const cId = gdata.cId;
297
363
 
298
- const isShow = this.colorAxis.find(({ id }) => id === cId)?.show;
299
-
364
+ let isShow;
365
+ if (this.isGradient) {
366
+ const { min, max } = this.valueOpt;
367
+ const ratio = convertToPercent(gdata.o - min, max - min);
368
+ const { start, end } = this.colorState[0];
369
+ isShow = (start <= ratio && ratio <= end) || gdata.o === -1;
370
+ } else {
371
+ isShow = this.colorState.find(({ id }) => id === cId)?.show;
372
+ }
300
373
  ctx.save();
374
+ ctx.shadowOffsetX = 2;
375
+ ctx.shadowOffsetY = 2;
376
+ ctx.shadowBlur = 4;
377
+
301
378
  if (x !== null && y !== null && isShow) {
302
379
  const color = gdata.dataColor;
303
- ctx.strokeStyle = Util.colorStringToRgba(color, 1);
304
- ctx.fillStyle = Util.colorStringToRgba(color, this.highlight.maxShadowOpacity);
305
- ctx.shadowColor = color;
306
- this.drawItem(ctx, x, y, w, h);
380
+ ctx.shadowColor = Util.colorStringToRgba('#605F5F');
381
+ ctx.strokeStyle = Util.colorStringToRgba(color);
382
+ ctx.fillStyle = Util.colorStringToRgba(color);
383
+ this.drawItem(ctx, x - 2, y - 2, w + 4, h + 4);
384
+
385
+ ctx.restore();
307
386
 
308
387
  if (this.showValue.use) {
309
388
  this.drawValueLabels({
310
389
  context: ctx,
311
390
  data: gdata,
312
- positions: {
313
- x,
314
- y,
315
- w,
316
- h,
317
- },
318
391
  });
319
392
  }
320
393
  }
321
-
322
- ctx.restore();
323
394
  }
324
395
 
325
396
  /**
@@ -102,6 +102,16 @@ export const AXIS_OPTION = {
102
102
  fitWidth: false,
103
103
  fitDir: 'right',
104
104
  },
105
+ title: {
106
+ use: false,
107
+ text: null,
108
+ fontWeight: 400,
109
+ fontSize: 12,
110
+ fontFamily: 'Roboto',
111
+ textAlign: 'right',
112
+ fontStyle: 'normal',
113
+ color: '#808080',
114
+ },
105
115
  };
106
116
 
107
117
  export const PLOT_LINE_OPTION = {
@@ -132,6 +142,7 @@ export const HEAT_MAP_OPTION = {
132
142
  show: true,
133
143
  highlight: {
134
144
  maxShadowOpacity: 0.4,
145
+ brightness: 150,
135
146
  },
136
147
  xAxisIndex: 0,
137
148
  yAxisIndex: 0,
@@ -127,7 +127,14 @@ export default {
127
127
  * @returns {string} computed value
128
128
  */
129
129
  getLabelStyle(style) {
130
- return `normal normal ${style.fontWeight} ${style.fontSize}px ${style.fontFamily}`;
130
+ const {
131
+ fontStyle = 'normal',
132
+ fontWeight = 'norma',
133
+ fontSize = '12',
134
+ fontFamily = 'Roboto',
135
+ } = style;
136
+
137
+ return `${fontStyle} normal ${fontWeight} ${fontSize}px ${fontFamily}`;
131
138
  },
132
139
 
133
140
  /**
@@ -54,7 +54,9 @@ const modules = {
54
54
  return new Pie(id, opt, index);
55
55
  } else if (type === 'heatMap') {
56
56
  this.seriesInfo.charts.heatMap.push(id);
57
- return new HeatMap(id, opt, this.options.heatMapColor);
57
+ const { heatMapColor, legend } = this.options;
58
+ const isGradient = legend.type === 'gradient';
59
+ return new HeatMap(id, opt, heatMapColor, isGradient);
58
60
  }
59
61
 
60
62
  return false;
@@ -418,7 +418,7 @@ const modules = {
418
418
  },
419
419
 
420
420
  getSeriesValueOptForHeatMap(series) {
421
- const data = series.data;
421
+ const { data, colorState, isGradient } = series;
422
422
  const colorOpt = this.options.heatMapColor;
423
423
  const categoryCnt = colorOpt.categoryCnt;
424
424
  const decimalPoint = colorOpt.decimalPoint;
@@ -441,10 +441,14 @@ const modules = {
441
441
  }
442
442
  });
443
443
 
444
- if (isExistError && series.colorAxis.length === categoryCnt) {
445
- series.colorAxis.push({
444
+ if (
445
+ isExistError
446
+ && !isGradient
447
+ && colorState.length === categoryCnt
448
+ ) {
449
+ colorState.push({
446
450
  id: `color#${categoryCnt}`,
447
- value: colorOpt.error,
451
+ color: colorOpt.error,
448
452
  state: 'normal',
449
453
  show: true,
450
454
  });