evui 3.3.39 → 3.3.40

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 (30) hide show
  1. package/dist/evui.common.js +2445 -188
  2. package/dist/evui.common.js.map +1 -1
  3. package/dist/evui.umd.js +2445 -188
  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 +69 -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/scale/scale.js +8 -3
  19. package/src/components/chart/style/chart.scss +14 -0
  20. package/src/components/chart/uses.js +319 -5
  21. package/src/components/chartBrush/ChartBrush.vue +298 -0
  22. package/src/components/chartBrush/chartBrush.core.js +453 -0
  23. package/src/components/chartBrush/index.js +9 -0
  24. package/src/components/chartBrush/uses.js +22 -0
  25. package/src/components/chartGroup/ChartGroup.vue +125 -0
  26. package/src/components/chartGroup/index.js +9 -0
  27. package/src/components/chartGroup/style/chartGroup.scss +5 -0
  28. package/src/components/chartGroup/uses.js +48 -0
  29. package/src/components/pagination/pageButton.vue +1 -0
  30. 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.40",
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: 0 });
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
  /**
@@ -707,7 +742,8 @@ class EvChart {
707
742
  this.axesY = this.createAxes('y', options.axesY);
708
743
  this.axesRange = this.getAxesRange();
709
744
  this.labelOffset = this.getLabelOffset();
710
- this.initSelectedInfo();
745
+
746
+ this.initSelectedInfo?.();
711
747
 
712
748
  this.render(updateInfo?.hitInfo);
713
749
 
@@ -771,10 +807,12 @@ class EvChart {
771
807
 
772
808
  /**
773
809
  * Resize chart
810
+ * @param {Function} promiseRes After evChart resize completes,
811
+ * callback completion status with promiseRes to draw a Brush over it.
774
812
  *
775
813
  * @returns {undefined}
776
814
  */
777
- resize() {
815
+ resize(promiseRes) {
778
816
  this.clear();
779
817
  this.bufferCtx.restore();
780
818
  this.bufferCtx.save();
@@ -783,6 +821,10 @@ class EvChart {
783
821
  this.initScale();
784
822
  this.chartRect = this.getChartRect();
785
823
  this.drawChart();
824
+
825
+ if (promiseRes) {
826
+ promiseRes(true);
827
+ }
786
828
  }
787
829
 
788
830
  /**