evui 3.4.129 → 3.4.130
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/evui.common.js +282 -706
- package/dist/evui.common.js.map +1 -1
- package/dist/evui.umd.js +282 -706
- package/dist/evui.umd.js.map +1 -1
- package/dist/evui.umd.min.js +1 -1
- package/dist/evui.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/chart/chart.core.js +2 -2
- package/src/components/chart/element/element.bar.js +61 -131
- package/src/components/chart/element/element.heatmap.js +3 -4
- package/src/components/chart/element/element.line.js +9 -11
- package/src/components/chart/element/element.tip.js +60 -120
- package/src/components/chart/helpers/helpers.util.js +15 -19
- package/src/components/chart/model/model.store.js +17 -40
- package/src/components/chart/plugins/plugins.interaction.js +8 -69
- package/src/components/chart/plugins/plugins.legend.js +6 -4
- package/src/components/chart/plugins/plugins.tooltip.js +4 -15
- package/src/components/chart/scale/scale.js +7 -17
- package/src/components/chart/scale/scale.linear.js +3 -183
- package/src/components/chart/uses.js +0 -1
|
@@ -160,29 +160,25 @@ export default {
|
|
|
160
160
|
return value;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
const isNegative = value < 0;
|
|
164
|
-
const absValue = Math.abs(value);
|
|
165
|
-
|
|
166
163
|
const assignLabelWith = (v, target, lb) => {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return isNegative ? `-${result}` : result;
|
|
164
|
+
if (v % target === 0) {
|
|
165
|
+
return `${(v / target).toFixed(decimalPoint)}${lb}`;
|
|
166
|
+
}
|
|
167
|
+
return `${(v / target).toFixed(1)}${lb}`;
|
|
172
168
|
};
|
|
173
169
|
|
|
174
|
-
if (
|
|
175
|
-
label = assignLabelWith(
|
|
176
|
-
} else if (
|
|
177
|
-
label = assignLabelWith(
|
|
178
|
-
} else if (
|
|
179
|
-
label = assignLabelWith(
|
|
180
|
-
} else if (
|
|
181
|
-
label = assignLabelWith(
|
|
182
|
-
} else if (
|
|
183
|
-
label = assignLabelWith(
|
|
170
|
+
if (value >= quad) {
|
|
171
|
+
label = assignLabelWith(value, quad, 'P');
|
|
172
|
+
} else if (value >= trill) {
|
|
173
|
+
label = assignLabelWith(value, trill, 'T');
|
|
174
|
+
} else if (value >= billi) {
|
|
175
|
+
label = assignLabelWith(value, billi, 'G');
|
|
176
|
+
} else if (value >= milli) {
|
|
177
|
+
label = assignLabelWith(value, milli, 'M');
|
|
178
|
+
} else if (value >= killo) {
|
|
179
|
+
label = assignLabelWith(value, 1000, 'K');
|
|
184
180
|
} else {
|
|
185
|
-
label =
|
|
181
|
+
label = value.toFixed(decimalPoint);
|
|
186
182
|
}
|
|
187
183
|
|
|
188
184
|
return label;
|
|
@@ -25,23 +25,21 @@ const modules = {
|
|
|
25
25
|
seriesIDs.forEach((seriesID) => {
|
|
26
26
|
const series = this.seriesList[seriesID];
|
|
27
27
|
const sData = data[seriesID];
|
|
28
|
-
const passingValue = series?.passingValue;
|
|
29
28
|
|
|
30
29
|
if (series && sData) {
|
|
31
30
|
series.data = this.addSeriesDSforScatter(sData);
|
|
32
|
-
series.minMax = this.getSeriesMinMax(series.data
|
|
31
|
+
series.minMax = this.getSeriesMinMax(series.data);
|
|
33
32
|
}
|
|
34
33
|
});
|
|
35
34
|
} else if (typeKey === 'heatMap') {
|
|
36
35
|
seriesIDs.forEach((seriesID) => {
|
|
37
36
|
const series = this.seriesList[seriesID];
|
|
38
|
-
const passingValue = series?.passingValue;
|
|
39
37
|
const sData = data[seriesID];
|
|
40
38
|
|
|
41
39
|
if (series && sData) {
|
|
42
40
|
series.labels = label;
|
|
43
41
|
series.data = this.addSeriesDSForHeatMap(sData);
|
|
44
|
-
series.minMax = this.getSeriesMinMax(series.data
|
|
42
|
+
series.minMax = this.getSeriesMinMax(series.data);
|
|
45
43
|
series.valueOpt = this.getSeriesValueOptForHeatMap(series);
|
|
46
44
|
}
|
|
47
45
|
});
|
|
@@ -70,7 +68,7 @@ const modules = {
|
|
|
70
68
|
} else {
|
|
71
69
|
series.data = this.addSeriesDS(sData, label, series.isExistGrp);
|
|
72
70
|
}
|
|
73
|
-
series.minMax = this.getSeriesMinMax(series.data
|
|
71
|
+
series.minMax = this.getSeriesMinMax(series.data);
|
|
74
72
|
}
|
|
75
73
|
});
|
|
76
74
|
}
|
|
@@ -410,21 +408,17 @@ const modules = {
|
|
|
410
408
|
const isHorizontal = this.options.horizontal;
|
|
411
409
|
const sdata = [];
|
|
412
410
|
|
|
413
|
-
const getBaseDataPosition = (baseIndex, dataIndex
|
|
411
|
+
const getBaseDataPosition = (baseIndex, dataIndex) => {
|
|
414
412
|
const nextBaseSeriesIndex = baseIndex - 1;
|
|
415
413
|
const baseSeries = this.seriesList[bsIds[baseIndex]];
|
|
416
414
|
const baseDataList = baseSeries.data;
|
|
417
415
|
const baseData = baseDataList[dataIndex];
|
|
418
416
|
const position = isHorizontal ? baseData?.x : baseData?.y;
|
|
417
|
+
const isPassingValue = baseSeries.passingValue === baseData?.o;
|
|
419
418
|
|
|
420
|
-
|
|
421
|
-
const isPassingValue = !Util.isNullOrUndefined(baseSeries?.passingValue)
|
|
422
|
-
&& baseSeries?.passingValue === baseValue;
|
|
423
|
-
const isSameSign = (curr >= 0 && baseValue >= 0) || (curr < 0 && baseValue < 0);
|
|
424
|
-
|
|
425
|
-
if (isPassingValue || position == null || !isSameSign || !baseSeries.show) {
|
|
419
|
+
if (isPassingValue || position == null || !baseSeries.show) {
|
|
426
420
|
if (nextBaseSeriesIndex > -1) {
|
|
427
|
-
return getBaseDataPosition(nextBaseSeriesIndex, dataIndex
|
|
421
|
+
return getBaseDataPosition(nextBaseSeriesIndex, dataIndex);
|
|
428
422
|
}
|
|
429
423
|
|
|
430
424
|
return 0;
|
|
@@ -435,7 +429,7 @@ const modules = {
|
|
|
435
429
|
|
|
436
430
|
data.forEach((curr, index) => {
|
|
437
431
|
const baseIndex = bsIds.length - 1 < 0 ? 0 : bsIds.length - 1;
|
|
438
|
-
let bdata = getBaseDataPosition(baseIndex, index
|
|
432
|
+
let bdata = getBaseDataPosition(baseIndex, index); // base(previous) series data
|
|
439
433
|
let odata = curr; // current series original data
|
|
440
434
|
let ldata = label[index]; // label data
|
|
441
435
|
let gdata = curr; // current series data which added previous series's value
|
|
@@ -588,34 +582,30 @@ const modules = {
|
|
|
588
582
|
return data;
|
|
589
583
|
},
|
|
590
584
|
|
|
585
|
+
|
|
591
586
|
/**
|
|
592
587
|
* Take series data to create min/max info for each series
|
|
593
588
|
* @param {object} data series data
|
|
594
589
|
*
|
|
595
590
|
* @returns {object} min/max info for series
|
|
596
591
|
*/
|
|
597
|
-
getSeriesMinMax(data
|
|
592
|
+
getSeriesMinMax(data) {
|
|
598
593
|
const def = { minX: null, minY: null, maxX: null, maxY: null, maxDomain: null };
|
|
599
594
|
const isHorizontal = this.options.horizontal;
|
|
600
595
|
|
|
601
596
|
if (data.length) {
|
|
602
|
-
const usePassingValue = !Util.isNullOrUndefined(passingValue);
|
|
603
|
-
|
|
604
597
|
return data.reduce((acc, p, index) => {
|
|
605
598
|
const minmax = acc;
|
|
606
599
|
const px = p.x?.value || p.x;
|
|
607
600
|
const py = p.y?.value || p.y;
|
|
608
|
-
const po = p.o?.value || p.o;
|
|
609
601
|
|
|
610
|
-
if (
|
|
602
|
+
if (px <= minmax.minX) {
|
|
611
603
|
minmax.minX = (px === null) ? 0 : px;
|
|
612
604
|
}
|
|
613
|
-
|
|
614
|
-
if ((usePassingValue ? (po !== passingValue && py <= minmax.minY) : py <= minmax.minY)) {
|
|
605
|
+
if (py <= minmax.minY) {
|
|
615
606
|
minmax.minY = (py === null) ? 0 : py;
|
|
616
607
|
}
|
|
617
|
-
|
|
618
|
-
if ((usePassingValue ? (po !== passingValue && px >= minmax.maxX) : px >= minmax.maxX)) {
|
|
608
|
+
if (px >= minmax.maxX) {
|
|
619
609
|
minmax.maxX = (px === null) ? 0 : px;
|
|
620
610
|
|
|
621
611
|
if (isHorizontal && px !== null) {
|
|
@@ -623,8 +613,7 @@ const modules = {
|
|
|
623
613
|
minmax.maxDomainIndex = index;
|
|
624
614
|
}
|
|
625
615
|
}
|
|
626
|
-
|
|
627
|
-
if ((usePassingValue ? (po !== passingValue && py >= minmax.maxY) : py >= minmax.maxY)) {
|
|
616
|
+
if (py >= minmax.maxY) {
|
|
628
617
|
minmax.maxY = (py === null) ? 0 : py;
|
|
629
618
|
|
|
630
619
|
if (!isHorizontal && py !== null) {
|
|
@@ -1267,25 +1256,13 @@ const modules = {
|
|
|
1267
1256
|
minmax.y[axisY].min = smm.minY;
|
|
1268
1257
|
}
|
|
1269
1258
|
}
|
|
1270
|
-
|
|
1271
|
-
const isExistGrp = this.seriesList[key].isExistGrp;
|
|
1272
|
-
const maxXisNegative = minmax.x[axisX].max < 0;
|
|
1273
|
-
|
|
1274
|
-
if (isExistGrp && maxXisNegative) {
|
|
1275
|
-
minmax.x[axisX].max = smm.maxX;
|
|
1276
|
-
minmax.x[axisX].maxSID = key;
|
|
1277
|
-
} else if (!minmax.x[axisX].max || smm.maxX >= minmax.x[axisX].max) {
|
|
1259
|
+
if (smm.maxX >= minmax.x[axisX].max) {
|
|
1278
1260
|
minmax.x[axisX].max = smm.maxX;
|
|
1279
1261
|
minmax.x[axisX].maxSID = key;
|
|
1280
1262
|
}
|
|
1281
|
-
|
|
1282
|
-
const maxYisNegative = minmax.y[axisY].max < 0;
|
|
1283
|
-
if (isExistGrp && maxYisNegative) {
|
|
1284
|
-
minmax.y[axisY].max = smm.maxY;
|
|
1285
|
-
minmax.y[axisY].maxSID = key;
|
|
1286
|
-
} else if (!minmax.y[axisY].max || smm.maxY >= minmax.y[axisY].max) {
|
|
1263
|
+
if (smm.maxY >= minmax.y[axisY].max) {
|
|
1287
1264
|
minmax.y[axisY].max = smm.maxY;
|
|
1288
|
-
minmax.y[
|
|
1265
|
+
minmax.y[axisX].maxSID = key;
|
|
1289
1266
|
}
|
|
1290
1267
|
}
|
|
1291
1268
|
|
|
@@ -79,29 +79,12 @@ const modules = {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
if (indicator.use && type !== 'pie' && type !== 'scatter' && type !== 'heatMap') {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
let label = this.getTimeLabel(offset);
|
|
85
|
-
const useAxisTrigger = tooltip.use && tooltip.trigger === 'axis' && type === 'line';
|
|
86
|
-
|
|
87
|
-
if (useAxisTrigger && Object.keys(hitInfo.items).length) {
|
|
88
|
-
const hitId = hitInfo.hitId || Object.keys(hitInfo.items)[0];
|
|
89
|
-
const hitItem = hitInfo.items[hitId];
|
|
90
|
-
|
|
91
|
-
if (hitItem && hitItem.data && hitItem.data.xp !== undefined
|
|
92
|
-
&& hitItem.data.yp !== undefined) {
|
|
93
|
-
indicatorOffset = [hitItem.data.xp, hitItem.data.yp];
|
|
94
|
-
label = this.data.labels[hitItem.index];
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
this.drawIndicator(indicatorOffset, indicator.color);
|
|
99
|
-
|
|
82
|
+
this.drawIndicator(offset, indicator.color);
|
|
83
|
+
const label = this.getTimeLabel(offset);
|
|
100
84
|
args.hoveredLabel = {
|
|
101
85
|
horizontal: this.options.horizontal,
|
|
102
86
|
label,
|
|
103
87
|
mousePosition: [e.clientX, e.clientY],
|
|
104
|
-
useAxisTrigger,
|
|
105
88
|
};
|
|
106
89
|
} else {
|
|
107
90
|
args.hoveredLabel = {
|
|
@@ -879,18 +862,11 @@ const modules = {
|
|
|
879
862
|
}
|
|
880
863
|
},
|
|
881
864
|
|
|
882
|
-
/**
|
|
883
|
-
* @typedef {object} HitInfo
|
|
884
|
-
* @property {object} items
|
|
885
|
-
* @property {string} hitId
|
|
886
|
-
* @property {object} maxTip
|
|
887
|
-
* @property {object} maxHighlight
|
|
888
|
-
*/
|
|
889
865
|
/**
|
|
890
866
|
* Find graph item on mouse position
|
|
891
867
|
* @param {array} offset return value from getMousePosition()
|
|
892
868
|
*
|
|
893
|
-
* @returns {
|
|
869
|
+
* @returns {object} hit item information
|
|
894
870
|
*/
|
|
895
871
|
findHitItem(offset) {
|
|
896
872
|
const sIds = Object.keys(this.seriesList);
|
|
@@ -898,29 +874,6 @@ const modules = {
|
|
|
898
874
|
const isHorizontal = !!this.options.horizontal;
|
|
899
875
|
const ctx = this.tooltipCtx;
|
|
900
876
|
|
|
901
|
-
// Cache for measureText to avoid repeated calculations
|
|
902
|
-
if (!this._measureTextCache) {
|
|
903
|
-
this._measureTextCache = new Map();
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
// Use sliding window cache based on text length to maintain frequently used entries
|
|
907
|
-
if (this._measureTextCache.size > 1000) {
|
|
908
|
-
const entries = Array.from(this._measureTextCache.entries());
|
|
909
|
-
|
|
910
|
-
// Sort by text length (shorter texts are likely more frequently used)
|
|
911
|
-
entries.sort(([keyA], [keyB]) => {
|
|
912
|
-
const textA = keyA.split('-')[0];
|
|
913
|
-
const textB = keyB.split('-')[0];
|
|
914
|
-
return textA.length - textB.length;
|
|
915
|
-
});
|
|
916
|
-
|
|
917
|
-
// Keep the first 500 entries (shorter texts)
|
|
918
|
-
this._measureTextCache.clear();
|
|
919
|
-
entries.slice(0, 500).forEach(([key, value]) => {
|
|
920
|
-
this._measureTextCache.set(key, value);
|
|
921
|
-
});
|
|
922
|
-
}
|
|
923
|
-
|
|
924
877
|
let hitId = null;
|
|
925
878
|
let maxs = '';
|
|
926
879
|
let maxsw = 0;
|
|
@@ -932,15 +885,10 @@ const modules = {
|
|
|
932
885
|
const sId = sIds[ix];
|
|
933
886
|
const series = this.seriesList[sId];
|
|
934
887
|
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
// eslint-disable-next-line no-continue
|
|
938
|
-
continue;
|
|
939
|
-
}
|
|
888
|
+
if (series.findGraphData) {
|
|
889
|
+
const item = series.findGraphData(offset, isHorizontal);
|
|
940
890
|
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
if (item?.data) {
|
|
891
|
+
if (item?.data) {
|
|
944
892
|
let gdata;
|
|
945
893
|
|
|
946
894
|
if (item.data.o === null && series.interpolation !== 'zero') {
|
|
@@ -958,17 +906,7 @@ const modules = {
|
|
|
958
906
|
seriesName: series.name,
|
|
959
907
|
itemData: item.data,
|
|
960
908
|
});
|
|
961
|
-
|
|
962
|
-
let sw = 1;
|
|
963
|
-
if (ctx) {
|
|
964
|
-
const cacheKey = `${formattedSeriesName}-${ctx.font}`;
|
|
965
|
-
if (this._measureTextCache.has(cacheKey)) {
|
|
966
|
-
sw = this._measureTextCache.get(cacheKey);
|
|
967
|
-
} else {
|
|
968
|
-
sw = ctx.measureText(formattedSeriesName).width;
|
|
969
|
-
this._measureTextCache.set(cacheKey, sw);
|
|
970
|
-
}
|
|
971
|
-
}
|
|
909
|
+
const sw = ctx ? ctx.measureText(formattedSeriesName).width : 1;
|
|
972
910
|
|
|
973
911
|
item.id = series.id;
|
|
974
912
|
item.name = formattedSeriesName;
|
|
@@ -1005,6 +943,7 @@ const modules = {
|
|
|
1005
943
|
}
|
|
1006
944
|
}
|
|
1007
945
|
}
|
|
946
|
+
}
|
|
1008
947
|
|
|
1009
948
|
hitId = hitId === null ? Object.keys(items)[0] : hitId;
|
|
1010
949
|
const maxHighlight = maxg !== null ? [maxSID, maxg] : null;
|
|
@@ -183,7 +183,8 @@ const modules = {
|
|
|
183
183
|
|
|
184
184
|
let useLegendSeries = [];
|
|
185
185
|
if (groups) {
|
|
186
|
-
useLegendSeries = groups.
|
|
186
|
+
useLegendSeries = groups.slice().reverse()
|
|
187
|
+
.filter(sId => this.seriesList[sId].showLegend)
|
|
187
188
|
.map(sId => [sId, this.seriesList[sId]]);
|
|
188
189
|
} else {
|
|
189
190
|
useLegendSeries = Object.entries(this.seriesList)
|
|
@@ -220,8 +221,9 @@ const modules = {
|
|
|
220
221
|
}
|
|
221
222
|
},
|
|
222
223
|
/**
|
|
223
|
-
* Adds legends for each group in `groups` array, iterating through each series
|
|
224
|
-
*
|
|
224
|
+
* Adds legends for each group in `groups` array, iterating through each series
|
|
225
|
+
* within the group in reverse order. This ensures the legends align with the series
|
|
226
|
+
* order as displayed in the chart. Only adds series with `showLegend` set to `true`.
|
|
225
227
|
*
|
|
226
228
|
* @param {Array} groups - Array of groups containing series identifiers.
|
|
227
229
|
* @param {Object} seriesList - Object containing all series, keyed by series ID.
|
|
@@ -230,7 +232,7 @@ const modules = {
|
|
|
230
232
|
*/
|
|
231
233
|
addLegendForGroups(groups, seriesList, useTable) {
|
|
232
234
|
groups.forEach((group) => {
|
|
233
|
-
group.forEach((sId) => {
|
|
235
|
+
group.slice().reverse().forEach((sId) => {
|
|
234
236
|
const series = seriesList[sId];
|
|
235
237
|
if (series && series.showLegend) {
|
|
236
238
|
this.addLegendBasedOnType(series, useTable);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { convertToPercent } from '@/common/utils';
|
|
2
2
|
import debounce from '@/common/utils.debounce';
|
|
3
|
-
import { inRange
|
|
3
|
+
import { inRange } from 'lodash-es';
|
|
4
4
|
import Canvas from '../helpers/helpers.canvas';
|
|
5
5
|
import Util from '../helpers/helpers.util';
|
|
6
6
|
|
|
@@ -783,7 +783,7 @@ const modules = {
|
|
|
783
783
|
y1: this.chartRect.y1 + this.labelOffset.top,
|
|
784
784
|
y2: this.chartRect.y2 - this.labelOffset.bottom,
|
|
785
785
|
};
|
|
786
|
-
const mouseXIp =
|
|
786
|
+
const mouseXIp = 1; // mouseInterpolation
|
|
787
787
|
const mouseYIp = 10;
|
|
788
788
|
const options = this.options;
|
|
789
789
|
|
|
@@ -858,7 +858,7 @@ const modules = {
|
|
|
858
858
|
*
|
|
859
859
|
* @returns {undefined}
|
|
860
860
|
*/
|
|
861
|
-
drawSyncedIndicator({ horizontal, label, mousePosition
|
|
861
|
+
drawSyncedIndicator({ horizontal, label, mousePosition }) {
|
|
862
862
|
if (!mousePosition || !!horizontal !== !!this.options.horizontal) {
|
|
863
863
|
return;
|
|
864
864
|
}
|
|
@@ -882,7 +882,6 @@ const modules = {
|
|
|
882
882
|
}
|
|
883
883
|
|
|
884
884
|
this.overlayClear();
|
|
885
|
-
|
|
886
885
|
const graphPos = {
|
|
887
886
|
x1: this.chartRect.x1 + this.labelOffset.left,
|
|
888
887
|
x2: this.chartRect.x2 - this.labelOffset.right,
|
|
@@ -890,17 +889,7 @@ const modules = {
|
|
|
890
889
|
y2: this.chartRect.y2 - this.labelOffset.bottom,
|
|
891
890
|
};
|
|
892
891
|
|
|
893
|
-
if (
|
|
894
|
-
const matchIndex = this.data.labels?.findIndex(l => l?.valueOf() === label?.valueOf());
|
|
895
|
-
if (matchIndex >= 0) {
|
|
896
|
-
const seriesId = Object.keys(this.seriesList)?.[0];
|
|
897
|
-
const dataPoint = this.seriesList?.[seriesId]?.data?.[matchIndex];
|
|
898
|
-
if (dataPoint?.xp !== undefined && dataPoint?.xp !== null) {
|
|
899
|
-
const yPosition = !isNil(dataPoint.yp) ? dataPoint.yp : (graphPos.y1 + graphPos.y2) / 2;
|
|
900
|
-
this.drawIndicator([dataPoint.xp, yPosition], this.options.indicator.color);
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
} else if (horizontal) {
|
|
892
|
+
if (horizontal) {
|
|
904
893
|
const chartHeight = graphPos.y2 - graphPos.y1;
|
|
905
894
|
const offsetY = (chartHeight * (label - fromTime)) / (toTime - fromTime) + graphPos.y1;
|
|
906
895
|
this.drawIndicator([graphPos.x2, offsetY], this.options.indicator.color);
|
|
@@ -93,8 +93,8 @@ class Scale {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
if (this.startToZero) {
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
minValue = 0;
|
|
97
|
+
}
|
|
98
98
|
|
|
99
99
|
if (maxValue === minValue) {
|
|
100
100
|
maxValue += 1;
|
|
@@ -138,7 +138,6 @@ class Scale {
|
|
|
138
138
|
|
|
139
139
|
/**
|
|
140
140
|
* With range information, calculate how many labels in axis
|
|
141
|
-
* linear type은 scale.linear.js에서 처리
|
|
142
141
|
* @param {object} range min/max information
|
|
143
142
|
*
|
|
144
143
|
* @returns {object} steps, interval, min/max graph value
|
|
@@ -340,13 +339,6 @@ class Scale {
|
|
|
340
339
|
ctx.beginPath();
|
|
341
340
|
ticks[ix] = axisMinForLabel + (ix * stepValue);
|
|
342
341
|
|
|
343
|
-
const isZeroLine = ticks[ix] === 0;
|
|
344
|
-
if (isZeroLine && this.zeroLineColor) {
|
|
345
|
-
ctx.strokeStyle = this.zeroLineColor;
|
|
346
|
-
} else {
|
|
347
|
-
ctx.strokeStyle = this.gridLineColor;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
342
|
linePosition = labelCenter + aliasPixel;
|
|
351
343
|
labelText = this.getLabelFormat(Math.min(axisMax, ticks[ix]), {
|
|
352
344
|
prev: ticks[ix - 1] ?? '',
|
|
@@ -443,17 +435,15 @@ class Scale {
|
|
|
443
435
|
}
|
|
444
436
|
|
|
445
437
|
const mergedPlotBandOpt = defaultsDeep({}, plotBand, PLOT_BAND_OPTION);
|
|
446
|
-
const { from
|
|
447
|
-
const from = userDefinedFrom ? Math.max(userDefinedFrom, axisMin) : axisMin;
|
|
448
|
-
const to = userDefinedTo ? Math.min(userDefinedTo, axisMax) : axisMax;
|
|
438
|
+
const { from, to, label: labelOpt } = mergedPlotBandOpt;
|
|
449
439
|
|
|
450
440
|
this.setPlotBandStyle(mergedPlotBandOpt);
|
|
451
441
|
|
|
452
442
|
let fromPos;
|
|
453
443
|
let toPos;
|
|
454
444
|
if (this.type === 'x') {
|
|
455
|
-
fromPos = Canvas.calculateX(from, axisMin, axisMax, xArea, minX);
|
|
456
|
-
toPos = Canvas.calculateX(to, axisMin, axisMax, xArea, minX);
|
|
445
|
+
fromPos = Canvas.calculateX(from ?? minX, axisMin, axisMax, xArea, minX);
|
|
446
|
+
toPos = Canvas.calculateX(to ?? maxX, axisMin, axisMax, xArea, minX);
|
|
457
447
|
|
|
458
448
|
if (fromPos === null || toPos === null) {
|
|
459
449
|
return;
|
|
@@ -461,8 +451,8 @@ class Scale {
|
|
|
461
451
|
|
|
462
452
|
this.drawXPlotBand(fromPos, toPos, minX, maxX, minY, maxY);
|
|
463
453
|
} else {
|
|
464
|
-
fromPos = Canvas.calculateY(from, axisMin, axisMax, yArea, maxY);
|
|
465
|
-
toPos = Canvas.calculateY(to, axisMin, axisMax, yArea, maxY);
|
|
454
|
+
fromPos = Canvas.calculateY(from ?? axisMin, axisMin, axisMax, yArea, maxY);
|
|
455
|
+
toPos = Canvas.calculateY(to ?? axisMax, axisMin, axisMax, yArea, maxY);
|
|
466
456
|
|
|
467
457
|
if (fromPos === null || toPos === null) {
|
|
468
458
|
return;
|
|
@@ -25,195 +25,15 @@ class LinearScale extends Scale {
|
|
|
25
25
|
* Calculate interval
|
|
26
26
|
* @param {object} range range information
|
|
27
27
|
*
|
|
28
|
-
* @returns {number}
|
|
28
|
+
* @returns {number} interval
|
|
29
29
|
*/
|
|
30
30
|
getInterval(range) {
|
|
31
|
-
if (this.interval) return this.interval;
|
|
32
|
-
|
|
33
31
|
const max = range.maxValue;
|
|
34
32
|
const min = range.minValue;
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
// step이 0이면 interval 계산 불가
|
|
38
|
-
if (!steps || steps <= 0) return 0;
|
|
39
|
-
|
|
40
|
-
// startToZero이고, 최소값이 음수일 경우 0을 반드시 포함
|
|
41
|
-
if (this.startToZero && min < 0) {
|
|
42
|
-
const totalRange = Math.abs(min) + Math.abs(max);
|
|
43
|
-
|
|
44
|
-
// 비율로 나눔
|
|
45
|
-
const negativeRatio = Math.abs(min) / totalRange;
|
|
46
|
-
const positiveRatio = Math.abs(max) / totalRange;
|
|
47
|
-
|
|
48
|
-
// 각 방향에 최소 1칸 이상 배정되도록 보장
|
|
49
|
-
let negativeSteps = Math.max(1, Math.round(negativeRatio * steps));
|
|
50
|
-
let positiveSteps = Math.max(1, steps - negativeSteps);
|
|
51
|
-
|
|
52
|
-
// 다시 합이 steps보다 커질 수도 있으니, 조정
|
|
53
|
-
if (negativeSteps + positiveSteps > steps) {
|
|
54
|
-
// 가장 큰 쪽에서 하나 줄임
|
|
55
|
-
if (negativeRatio > positiveRatio) {
|
|
56
|
-
negativeSteps -= 1;
|
|
57
|
-
} else {
|
|
58
|
-
positiveSteps -= 1;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return Math.ceil(
|
|
63
|
-
Math.max(
|
|
64
|
-
Math.abs(min) / (negativeSteps || 1),
|
|
65
|
-
Math.abs(max) / (positiveSteps || 1),
|
|
66
|
-
),
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
return Math.ceil((max - min) / steps);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* With range information, calculate how many labels in axis
|
|
74
|
-
* @param {object} range min/max information
|
|
75
|
-
*
|
|
76
|
-
* @returns {object} steps, interval, min/max graph value
|
|
77
|
-
*/
|
|
78
|
-
calculateSteps(range) {
|
|
79
|
-
const { maxValue, minValue } = range;
|
|
80
|
-
let { maxSteps = 1 } = range;
|
|
81
|
-
|
|
82
|
-
let interval = this.getInterval(range);
|
|
83
|
-
let graphMin = 0;
|
|
84
|
-
let graphMax = 0;
|
|
85
|
-
|
|
86
|
-
// 그래프 최대/최소 값 계산
|
|
87
|
-
if (minValue >= 0) {
|
|
88
|
-
// 전부 양수
|
|
89
|
-
graphMin = +minValue;
|
|
90
|
-
graphMax = Math.ceil(maxValue / interval) * interval;
|
|
91
|
-
} else if (maxValue >= 0) {
|
|
92
|
-
// 양수/음수 혼합
|
|
93
|
-
graphMin = Math.floor(minValue / interval) * interval;
|
|
94
|
-
graphMax = Math.ceil(maxValue / interval) * interval;
|
|
95
|
-
} else {
|
|
96
|
-
// 전부 음수
|
|
97
|
-
graphMax = +maxValue;
|
|
98
|
-
graphMin = Math.floor(minValue / interval) * interval;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const graphRange = graphMax - graphMin;
|
|
102
|
-
let numberOfSteps = Math.round(graphRange / interval);
|
|
103
|
-
|
|
104
|
-
// 특수 케이스: 양수 최소값, 최대값이 1일 경우
|
|
105
|
-
if (minValue > 0 && maxValue === 1) {
|
|
106
|
-
if (!this.decimalPoint) {
|
|
107
|
-
interval = 1;
|
|
108
|
-
numberOfSteps = 1;
|
|
109
|
-
maxSteps = 1;
|
|
110
|
-
} else if (maxSteps > 2) {
|
|
111
|
-
interval = 0.2;
|
|
112
|
-
numberOfSteps = 5;
|
|
113
|
-
maxSteps = 5;
|
|
114
|
-
} else {
|
|
115
|
-
interval = 0.5;
|
|
116
|
-
numberOfSteps = 2;
|
|
117
|
-
maxSteps = 2;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
33
|
+
const step = range.maxSteps;
|
|
120
34
|
|
|
121
|
-
|
|
122
|
-
while (numberOfSteps > maxSteps) {
|
|
123
|
-
interval *= 2;
|
|
124
|
-
numberOfSteps = Math.round(graphRange / interval);
|
|
125
|
-
interval = Math.ceil(graphRange / numberOfSteps);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (graphRange > (numberOfSteps * interval)) {
|
|
129
|
-
interval = Math.ceil(graphRange / numberOfSteps);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return {
|
|
133
|
-
steps: numberOfSteps,
|
|
134
|
-
interval,
|
|
135
|
-
graphMin,
|
|
136
|
-
graphMax,
|
|
137
|
-
};
|
|
35
|
+
return this.interval ? this.interval : Math.ceil((max - min) / step);
|
|
138
36
|
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Calculate min/max value, label and size information for axis
|
|
142
|
-
* @param {object} minMax min/max information
|
|
143
|
-
* @param {object} scrollbarOpt scrollbar option
|
|
144
|
-
*
|
|
145
|
-
* @returns {object} min/max value and label
|
|
146
|
-
*/
|
|
147
|
-
calculateScaleRange(minMax, scrollbarOpt) {
|
|
148
|
-
let maxValue;
|
|
149
|
-
let minValue;
|
|
150
|
-
let isDefaultMaxSameAsMin = false;
|
|
151
|
-
|
|
152
|
-
const range = scrollbarOpt?.use ? scrollbarOpt?.range : this.range;
|
|
153
|
-
if (Array.isArray(range) && range?.length === 2) {
|
|
154
|
-
if (this.options.type === 'heatMap') {
|
|
155
|
-
maxValue = range[1] > +minMax.max ? +minMax.max : range[1];
|
|
156
|
-
minValue = range[0] < +minMax.min ? +minMax.min : range[0];
|
|
157
|
-
} else {
|
|
158
|
-
maxValue = range[1];
|
|
159
|
-
minValue = range[0];
|
|
160
|
-
}
|
|
161
|
-
} else if (typeof range === 'function') {
|
|
162
|
-
[minValue, maxValue] = range(minMax.min, minMax.max);
|
|
163
|
-
} else {
|
|
164
|
-
maxValue = minMax.max;
|
|
165
|
-
minValue = minMax.min;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// autoScaleRatio 적용 케이스
|
|
169
|
-
if (this.autoScaleRatio) {
|
|
170
|
-
const temp = maxValue;
|
|
171
|
-
// 양수 방향에만 autoScaleRatio 적용
|
|
172
|
-
maxValue = Math.ceil(maxValue * (this.autoScaleRatio + 1));
|
|
173
|
-
|
|
174
|
-
if (maxValue > 0 && minValue < 0) {
|
|
175
|
-
// 양수/음수 혼합 케이스 -- 음수 방향에도 maxValue 증가분만큼 더하기
|
|
176
|
-
const diff = temp - maxValue;
|
|
177
|
-
minValue += diff;
|
|
178
|
-
} else if (maxValue < 0 && minValue < 0) {
|
|
179
|
-
// 전부 음수 케이스 -- 음수 방향에도 autoScaleRatio 적용
|
|
180
|
-
minValue = Math.ceil(minValue * (this.autoScaleRatio + 1));
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// 0 기준 축 설정 케이스
|
|
185
|
-
if (this.startToZero) {
|
|
186
|
-
if (minValue > 0) {
|
|
187
|
-
minValue = 0;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
if (maxValue < 0) {
|
|
191
|
-
maxValue = 0;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (maxValue === minValue) {
|
|
196
|
-
maxValue += 1;
|
|
197
|
-
isDefaultMaxSameAsMin = true;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const minLabel = this.getLabelFormat(minValue);
|
|
201
|
-
const maxLabel = this.getLabelFormat(maxValue, {
|
|
202
|
-
isMaxValueSameAsMin: isDefaultMaxSameAsMin,
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
return {
|
|
206
|
-
min: minValue,
|
|
207
|
-
max: maxValue,
|
|
208
|
-
minLabel,
|
|
209
|
-
maxLabel,
|
|
210
|
-
size: Util.calcTextSize(
|
|
211
|
-
maxLabel,
|
|
212
|
-
Util.getLabelStyle(this.labelStyle),
|
|
213
|
-
this.labelStyle?.padding,
|
|
214
|
-
),
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
37
|
}
|
|
218
38
|
|
|
219
39
|
export default LinearScale;
|