evui 3.3.39 → 3.3.41

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.
Files changed (31) hide show
  1. package/dist/evui.common.js +2477 -197
  2. package/dist/evui.common.js.map +1 -1
  3. package/dist/evui.umd.js +2477 -197
  4. package/dist/evui.umd.js.map +1 -1
  5. package/dist/evui.umd.min.js +1 -1
  6. package/dist/evui.umd.min.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/components/chart/Chart.vue +95 -5
  9. package/src/components/chart/ChartToolbar.vue +52 -0
  10. package/src/components/chart/chart.core.js +71 -27
  11. package/src/components/chart/chartZoom.core.js +479 -0
  12. package/src/components/chart/element/element.line.js +2 -1
  13. package/src/components/chart/element/element.scatter.js +8 -2
  14. package/src/components/chart/element/element.tip.js +41 -33
  15. package/src/components/chart/model/model.store.js +34 -5
  16. package/src/components/chart/plugins/plugins.interaction.js +28 -4
  17. package/src/components/chart/plugins/plugins.legend.js +11 -1
  18. package/src/components/chart/plugins/plugins.title.js +13 -8
  19. package/src/components/chart/scale/scale.js +8 -3
  20. package/src/components/chart/style/chart.scss +14 -0
  21. package/src/components/chart/uses.js +329 -6
  22. package/src/components/chartBrush/ChartBrush.vue +298 -0
  23. package/src/components/chartBrush/chartBrush.core.js +458 -0
  24. package/src/components/chartBrush/index.js +9 -0
  25. package/src/components/chartBrush/uses.js +22 -0
  26. package/src/components/chartGroup/ChartGroup.vue +125 -0
  27. package/src/components/chartGroup/index.js +9 -0
  28. package/src/components/chartGroup/style/chartGroup.scss +5 -0
  29. package/src/components/chartGroup/uses.js +48 -0
  30. package/src/components/pagination/pageButton.vue +1 -0
  31. package/src/main.js +4 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evui",
3
- "version": "3.3.39",
3
+ "version": "3.3.41",
4
4
  "description": "A EXEM Library project",
5
5
  "author": "exem <dev_client@ex-em.com>",
6
6
  "license": "MIT",
@@ -1,4 +1,14 @@
1
1
  <template>
2
+ <div
3
+ v-if="zoomOptions.toolbar.show && !injectIsChartGroup"
4
+ ref="evChartToolbarRef"
5
+ >
6
+ <ev-chart-toolbar
7
+ :toolbar="zoomOptions.toolbar"
8
+ @on-click-toolbar="onClickToolbar"
9
+ />
10
+ </div>
11
+
2
12
  <div
3
13
  ref="wrapper"
4
14
  v-resize="onResize"
@@ -8,13 +18,17 @@
8
18
  </template>
9
19
 
10
20
  <script>
11
- import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
21
+ import { onMounted, onBeforeUnmount, watch, onDeactivated, inject, toRef, computed } from 'vue';
12
22
  import { cloneDeep, isEqual, debounce } from 'lodash-es';
13
23
  import EvChart from './chart.core';
14
- import { useModel, useWrapper } from './uses';
24
+ import EvChartToolbar from './ChartToolbar';
25
+ import { useModel, useWrapper, useZoomModel } from './uses';
15
26
 
16
27
  export default {
17
28
  name: 'EvChart',
29
+ components: {
30
+ EvChartToolbar,
31
+ },
18
32
  props: {
19
33
  selectedItem: {
20
34
  type: Object,
@@ -40,6 +54,14 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
40
54
  type: Number,
41
55
  default: 0,
42
56
  },
57
+ zoomStartIdx: {
58
+ type: Number,
59
+ default: 0,
60
+ },
61
+ zoomEndIdx: {
62
+ type: Number,
63
+ default: 0,
64
+ },
43
65
  },
44
66
  emits: [
45
67
  'click',
@@ -48,9 +70,15 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
48
70
  'update:selectedItem',
49
71
  'update:selectedLabel',
50
72
  'update:selectedSeries',
73
+ 'update:zoomStartIdx',
74
+ 'update:zoomEndIdx',
51
75
  ],
52
76
  setup(props) {
53
77
  let evChart = null;
78
+ const injectIsChartGroup = inject('isChartGroup', false);
79
+ const injectBrushSeries = inject('brushSeries', { list: [], chartIdx: null });
80
+ const injectGroupSelectedLabel = inject('groupSelectedLabel', null);
81
+ const injectBrushIdx = inject('brushIdx', { start: 0, end: -1 });
54
82
 
55
83
  const {
56
84
  eventListeners,
@@ -59,10 +87,12 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
59
87
  selectSeriesInfo,
60
88
  getNormalizedData,
61
89
  getNormalizedOptions,
62
- } = useModel();
90
+ } = useModel(injectGroupSelectedLabel);
63
91
 
64
92
  const normalizedData = getNormalizedData(props.data);
65
93
  const normalizedOptions = getNormalizedOptions(props.options);
94
+ const selectedLabel = computed(() => props.selectedLabel);
95
+ const selectedItem = computed(() => props.selectedItem);
66
96
 
67
97
  const {
68
98
  wrapper,
@@ -71,6 +101,21 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
71
101
  normalizedOptions,
72
102
  );
73
103
 
104
+ const {
105
+ evChartZoomOptions,
106
+ evChartToolbarRef,
107
+
108
+ createEvChartZoom,
109
+ setOptionsForUseZoom,
110
+ setDataForUseZoom,
111
+ controlZoomIdx,
112
+ onClickToolbar,
113
+ } = useZoomModel(
114
+ normalizedOptions,
115
+ { wrapper, evChartGroupRef: null },
116
+ props.selectedLabel ? selectedLabel : selectedItem,
117
+ );
118
+
74
119
  const createChart = () => {
75
120
  let selected;
76
121
  if (normalizedOptions.selectLabel.use) {
@@ -86,12 +131,17 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
86
131
  eventListeners,
87
132
  selectItemInfo,
88
133
  selected,
134
+ injectBrushSeries,
89
135
  );
90
136
  };
91
137
 
92
138
  const drawChart = () => {
93
139
  if (evChart) {
94
140
  evChart.init();
141
+
142
+ if (!injectIsChartGroup && normalizedOptions.zoom.toolbar.show) {
143
+ createEvChartZoom();
144
+ }
95
145
  }
96
146
  };
97
147
 
@@ -106,6 +156,10 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
106
156
  updateSelTip: { update: false, keepDomain: false },
107
157
  updateLegend: isUpdateLegendType,
108
158
  });
159
+
160
+ if (!injectIsChartGroup) {
161
+ setOptionsForUseZoom(newOpt);
162
+ }
109
163
  }, { deep: true, flush: 'post' });
110
164
 
111
165
  watch(() => props.data, (chartData) => {
@@ -123,14 +177,38 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
123
177
  updateSelTip: { update: true, keepDomain: false },
124
178
  updateData: isUpdateData,
125
179
  });
180
+
181
+ if (!injectIsChartGroup && isUpdateData) {
182
+ setDataForUseZoom(newData);
183
+ }
126
184
  }, { deep: true, flush: 'post' });
127
185
 
128
- watch(() => props.selectedItem, (newValue) => {
186
+ if (injectIsChartGroup && !injectGroupSelectedLabel?.value) {
187
+ watch(() => injectBrushIdx.start, (curBrushStartIdx, prevBrushStartIdx) => {
188
+ if (selectedLabel?.value) {
189
+ for (let idx = 0; idx < selectedLabel.value.dataIndex.length; idx++) {
190
+ if (curBrushStartIdx >= (prevBrushStartIdx ?? 0)) {
191
+ selectedLabel.value.dataIndex[idx] -= curBrushStartIdx - (prevBrushStartIdx ?? 0);
192
+ } else {
193
+ selectedLabel.value.dataIndex[idx] += prevBrushStartIdx - curBrushStartIdx;
194
+ }
195
+ }
196
+ } else if (selectedItem?.value) {
197
+ if (curBrushStartIdx >= (prevBrushStartIdx ?? 0)) {
198
+ selectedItem.value.dataIndex -= curBrushStartIdx - (prevBrushStartIdx ?? 0);
199
+ } else {
200
+ selectedItem.value.dataIndex += prevBrushStartIdx - curBrushStartIdx;
201
+ }
202
+ }
203
+ });
204
+ }
205
+
206
+ watch(() => selectedItem.value, (newValue) => {
129
207
  const chartType = props.options.type;
130
208
  evChart.selectItemByData(newValue, chartType);
131
209
  }, { deep: true, flush: 'post' });
132
210
 
133
- watch(() => props.selectedLabel, (newValue) => {
211
+ watch(() => (injectGroupSelectedLabel?.value ?? selectedLabel.value), (newValue) => {
134
212
  if (newValue.dataIndex) {
135
213
  evChart.renderWithSelected(newValue.dataIndex);
136
214
  }
@@ -142,6 +220,12 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
142
220
  }
143
221
  }, { deep: true, flush: 'post' });
144
222
 
223
+ if (!injectIsChartGroup) {
224
+ watch(() => [props.zoomStartIdx, props.zoomEndIdx], ([zoomStartIdx, zoomEndIdx]) => {
225
+ controlZoomIdx(zoomStartIdx, zoomEndIdx);
226
+ });
227
+ }
228
+
145
229
  onMounted(async () => {
146
230
  await createChart();
147
231
  await drawChart();
@@ -179,6 +263,12 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
179
263
  wrapperStyle,
180
264
  onResize,
181
265
  redraw,
266
+
267
+ evChartToolbarRef,
268
+ injectIsChartGroup,
269
+ onClickToolbar,
270
+ normalizedOptions,
271
+ zoomOptions: toRef(evChartZoomOptions, 'zoom'),
182
272
  };
183
273
  },
184
274
  };
@@ -0,0 +1,52 @@
1
+ <template>
2
+ <div class="ev-chart__toolbar__wrapper">
3
+ <div class="ev-chart__toolbar__wrapper__icon">
4
+ <ev-icon
5
+ v-for="(option, iconType) in $props.toolbar.items"
6
+ :key="`${iconType}-${option.icon}`"
7
+ :class="iconType"
8
+ :icon="option.icon"
9
+ :size="option.size"
10
+ :title="option.title"
11
+ @click="$emit('onClickToolbar', $event, iconType)"
12
+ />
13
+ </div>
14
+ </div>
15
+ </template>
16
+
17
+ <script>
18
+ export default {
19
+ name: 'EvChartToolbar',
20
+ props: {
21
+ toolbar: {
22
+ type: Object,
23
+ default: () => ({}),
24
+ },
25
+ },
26
+ emits: ['onClickToolbar'],
27
+ };
28
+ </script>
29
+
30
+ <style lang="scss" scoped>
31
+ .ev-chart__toolbar__wrapper {
32
+ height: 30px;
33
+ text-align: right;
34
+ padding-right: 30px;
35
+
36
+ &__icon {
37
+ i {
38
+ pointer-events: none;
39
+ opacity: 0.5;
40
+ cursor: pointer;
41
+ }
42
+
43
+ i + i {
44
+ margin-left: 10px;
45
+ }
46
+
47
+ .active {
48
+ font-weight: bold;
49
+ }
50
+ }
51
+ }
52
+ </style>
@@ -14,28 +14,40 @@ 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, defaultSelectItemInfo, defaultSelectInfo) {
17
+ constructor(
18
+ target,
19
+ data,
20
+ options,
21
+ listeners,
22
+ defaultSelectItemInfo,
23
+ defaultSelectInfo,
24
+ brushSeries,
25
+ ) {
18
26
  Object.keys(Model).forEach(key => Object.assign(this, Model[key]));
19
- Object.assign(this, Title);
20
- Object.assign(this, Legend);
21
- Object.assign(this, Interaction);
22
- Object.assign(this, Tooltip);
23
- Object.assign(this, Pie);
24
- Object.assign(this, Tip);
27
+
28
+ if (!options.brush) {
29
+ Object.assign(this, Tooltip);
30
+ Object.assign(this, Interaction);
31
+ Object.assign(this, Tip);
32
+ Object.assign(this, Legend);
33
+ Object.assign(this, Pie);
34
+ Object.assign(this, Title);
35
+ }
25
36
 
26
37
  if (options.type === 'heatMap' && options.legend.type === 'gradient') {
27
38
  Object.assign(this, GradientLegend);
28
39
  }
29
40
 
41
+ this.brushSeries = brushSeries;
30
42
  this.target = target;
31
43
  this.data = data;
32
44
  this.options = options;
33
45
  this.listeners = listeners;
34
46
 
35
47
  this.wrapperDOM = document.createElement('div');
36
- this.wrapperDOM.className = 'ev-chart-wrapper';
48
+ this.wrapperDOM.className = options.brush ? 'ev-chart-brush-wrapper' : 'ev-chart-wrapper';
37
49
  this.chartDOM = document.createElement('div');
38
- this.chartDOM.className = 'ev-chart-container';
50
+ this.chartDOM.className = options.brush ? 'ev-chart-brush-container' : 'ev-chart-container';
39
51
  this.wrapperDOM.appendChild(this.chartDOM);
40
52
  this.target.appendChild(this.wrapperDOM);
41
53
 
@@ -45,19 +57,25 @@ class EvChart {
45
57
  this.bufferCanvas = document.createElement('canvas');
46
58
  this.bufferCanvas.setAttribute('style', 'display: block;');
47
59
  this.bufferCtx = this.bufferCanvas.getContext('2d');
48
- this.overlayCanvas = document.createElement('canvas');
49
- this.overlayCanvas.setAttribute('style', 'display: block;');
50
- this.overlayCtx = this.overlayCanvas.getContext('2d');
51
60
 
52
61
  this.pixelRatio = window.devicePixelRatio || 1;
53
62
  this.oldPixelRatio = this.pixelRatio;
54
63
 
55
64
  this.chartDOM.appendChild(this.displayCanvas);
56
- this.chartDOM.appendChild(this.overlayCanvas);
57
65
 
58
- this.overlayCanvas.style.position = 'absolute';
59
- this.overlayCanvas.style.top = '0px';
60
- this.overlayCanvas.style.left = '0px';
66
+ if (!options.brush) {
67
+ this.overlayCanvas = document.createElement('canvas');
68
+ this.overlayCanvas.setAttribute('style', 'display: block; z-index: 2;');
69
+ this.overlayCanvas.setAttribute('class', 'overlay-canvas');
70
+ this.overlayCtx = this.overlayCanvas.getContext('2d');
71
+
72
+ this.chartDOM.appendChild(this.overlayCanvas);
73
+
74
+ this.overlayCanvas.style.position = 'absolute';
75
+ this.overlayCanvas.style.top = '0px';
76
+ this.overlayCanvas.style.left = '0px';
77
+ }
78
+
61
79
 
62
80
  this.isInitLegend = false;
63
81
  this.isInitTitle = false;
@@ -97,10 +115,12 @@ class EvChart {
97
115
 
98
116
  this.axesRange = this.getAxesRange();
99
117
  this.labelOffset = this.getLabelOffset();
100
- this.initSelectedInfo();
118
+
119
+ this.initSelectedInfo?.();
101
120
 
102
121
  this.drawChart();
103
122
 
123
+
104
124
  if (tooltip.use) {
105
125
  this.createTooltipDOM();
106
126
 
@@ -109,7 +129,7 @@ class EvChart {
109
129
  }
110
130
  }
111
131
 
112
- this.createEventFunctions();
132
+ this.createEventFunctions?.();
113
133
  this.isInit = true;
114
134
  }
115
135
 
@@ -151,7 +171,9 @@ class EvChart {
151
171
  this.axesSteps = this.calculateSteps();
152
172
  this.drawAxis(hitInfo);
153
173
  this.drawSeries(hitInfo);
174
+
154
175
  this.drawTip();
176
+
155
177
  if (this.bufferCanvas) {
156
178
  this.displayCtx.drawImage(this.bufferCanvas, 0, 0);
157
179
  }
@@ -164,7 +186,7 @@ class EvChart {
164
186
  * @returns {undefined}
165
187
  */
166
188
  drawSeries(hitInfo) {
167
- const { maxTip, selectLabel, selectItem, selectSeries } = this.options;
189
+ const { maxTip, selectLabel, selectItem, selectSeries, brush, displayOverflow } = this.options;
168
190
 
169
191
  const opt = {
170
192
  ctx: this.bufferCtx,
@@ -175,6 +197,8 @@ class EvChart {
175
197
  selectLabel: { option: selectLabel, selected: this.defaultSelectInfo },
176
198
  selectSeries: { option: selectSeries, selected: this.defaultSelectInfo },
177
199
  overlayCtx: this.overlayCtx,
200
+ isBrush: !!brush,
201
+ displayOverflow,
178
202
  };
179
203
 
180
204
  let showIndex = 0;
@@ -290,11 +314,13 @@ class EvChart {
290
314
  tipLocationInfo = this.lastHitInfo;
291
315
  } else if (this.defaultSelectItemInfo) {
292
316
  tipLocationInfo = this.getItem(this.defaultSelectItemInfo, false);
317
+ } else if (this.defaultSelectInfo && this.options.selectLabel.use) {
318
+ tipLocationInfo = this.getItem(this.defaultSelectInfo, false);
293
319
  } else {
294
320
  tipLocationInfo = null;
295
321
  }
296
322
 
297
- this.drawTips(tipLocationInfo);
323
+ this.drawTips?.(tipLocationInfo);
298
324
  }
299
325
 
300
326
  /**
@@ -437,7 +463,10 @@ class EvChart {
437
463
  }
438
464
 
439
465
  this.bufferCtx.scale(this.pixelRatio, this.pixelRatio);
440
- this.overlayCtx.scale(this.pixelRatio, this.pixelRatio);
466
+
467
+ if (this.overlayCtx) {
468
+ this.overlayCtx.scale(this.pixelRatio, this.pixelRatio);
469
+ }
441
470
  }
442
471
 
443
472
  /**
@@ -518,8 +547,11 @@ class EvChart {
518
547
  this.displayCanvas.style.width = `${width}px`;
519
548
  this.bufferCanvas.width = width * this.pixelRatio;
520
549
  this.bufferCanvas.style.width = `${width}px`;
521
- this.overlayCanvas.width = width * this.pixelRatio;
522
- this.overlayCanvas.style.width = `${width}px`;
550
+
551
+ if (this.overlayCanvas) {
552
+ this.overlayCanvas.width = width * this.pixelRatio;
553
+ this.overlayCanvas.style.width = `${width}px`;
554
+ }
523
555
  }
524
556
 
525
557
  /**
@@ -537,8 +569,11 @@ class EvChart {
537
569
  this.displayCanvas.style.height = `${height}px`;
538
570
  this.bufferCanvas.height = height * this.pixelRatio;
539
571
  this.bufferCanvas.style.height = `${height}px`;
540
- this.overlayCanvas.height = height * this.pixelRatio;
541
- this.overlayCanvas.style.height = `${height}px`;
572
+
573
+ if (this.overlayCanvas) {
574
+ this.overlayCanvas.height = height * this.pixelRatio;
575
+ this.overlayCanvas.style.height = `${height}px`;
576
+ }
542
577
  }
543
578
 
544
579
  /**
@@ -672,6 +707,8 @@ class EvChart {
672
707
  if (options.title.show) {
673
708
  if (!this.isInitTitle) {
674
709
  this.initTitle();
710
+ } else {
711
+ this.updateTitle();
675
712
  }
676
713
 
677
714
  this.showTitle();
@@ -707,7 +744,8 @@ class EvChart {
707
744
  this.axesY = this.createAxes('y', options.axesY);
708
745
  this.axesRange = this.getAxesRange();
709
746
  this.labelOffset = this.getLabelOffset();
710
- this.initSelectedInfo();
747
+
748
+ this.initSelectedInfo?.();
711
749
 
712
750
  this.render(updateInfo?.hitInfo);
713
751
 
@@ -771,10 +809,12 @@ class EvChart {
771
809
 
772
810
  /**
773
811
  * Resize chart
812
+ * @param {Function} promiseRes After evChart resize completes,
813
+ * callback completion status with promiseRes to draw a Brush over it.
774
814
  *
775
815
  * @returns {undefined}
776
816
  */
777
- resize() {
817
+ resize(promiseRes) {
778
818
  this.clear();
779
819
  this.bufferCtx.restore();
780
820
  this.bufferCtx.save();
@@ -783,6 +823,10 @@ class EvChart {
783
823
  this.initScale();
784
824
  this.chartRect = this.getChartRect();
785
825
  this.drawChart();
826
+
827
+ if (promiseRes) {
828
+ promiseRes(true);
829
+ }
786
830
  }
787
831
 
788
832
  /**