evui 3.4.123 → 3.4.201
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 +506 -190
- package/dist/evui.common.js.map +1 -1
- package/dist/evui.umd.js +506 -190
- 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/element/element.bar.js +131 -61
- package/src/components/chart/element/element.line.js +6 -5
- package/src/components/chart/element/element.tip.js +120 -60
- package/src/components/chart/helpers/helpers.util.js +19 -15
- package/src/components/chart/model/model.store.js +40 -17
- package/src/components/chart/plugins/plugins.legend.js +4 -6
- package/src/components/chart/scale/scale.js +19 -9
- package/src/components/chart/scale/scale.linear.js +183 -3
package/package.json
CHANGED
|
@@ -76,8 +76,14 @@ class Bar {
|
|
|
76
76
|
|
|
77
77
|
const xArea = chartRect.chartWidth - (labelOffset.left + labelOffset.right);
|
|
78
78
|
const yArea = chartRect.chartHeight - (labelOffset.top + labelOffset.bottom);
|
|
79
|
-
|
|
80
|
-
const
|
|
79
|
+
|
|
80
|
+
const xAxisPosition = chartRect.x1 + labelOffset.left;
|
|
81
|
+
const yAxisPosition = chartRect.y2 - labelOffset.bottom;
|
|
82
|
+
const xZeroPosition = Canvas.calculateX(0, minmaxX.graphMin, minmaxX.graphMax, xArea);
|
|
83
|
+
const yZeroPosition = Canvas.calculateY(0, minmaxY.graphMin, minmaxY.graphMax, yArea);
|
|
84
|
+
|
|
85
|
+
const xsp = isHorizontal ? xAxisPosition + xZeroPosition : xAxisPosition;
|
|
86
|
+
const ysp = isHorizontal ? yAxisPosition : yAxisPosition + yZeroPosition;
|
|
81
87
|
|
|
82
88
|
const dArea = isHorizontal ? yArea : xArea;
|
|
83
89
|
const cArea = dArea / (totalCount || 1);
|
|
@@ -135,7 +141,6 @@ class Bar {
|
|
|
135
141
|
const item = this.data[i]; // 실제 데이터 인덱스에 해당하는 항목
|
|
136
142
|
if (item) {
|
|
137
143
|
// 스크롤 offset(minIndex)만큼 보정해서 그리기
|
|
138
|
-
|
|
139
144
|
let categoryPoint;
|
|
140
145
|
if (isHorizontal) {
|
|
141
146
|
categoryPoint = ysp - (cArea * (screenIndex)) - cPad;
|
|
@@ -143,6 +148,7 @@ class Bar {
|
|
|
143
148
|
categoryPoint = xsp + (cArea * (screenIndex)) + cPad;
|
|
144
149
|
}
|
|
145
150
|
|
|
151
|
+
// 기본 위치 설정
|
|
146
152
|
if (isHorizontal) {
|
|
147
153
|
x = xsp;
|
|
148
154
|
y = Math.round(categoryPoint - ((bArea * barSeriesX) - (h + bPad)));
|
|
@@ -151,22 +157,40 @@ class Bar {
|
|
|
151
157
|
y = ysp;
|
|
152
158
|
}
|
|
153
159
|
|
|
160
|
+
// 너비 / 높이 계산, 스택의 경우 위치 값 재계산
|
|
154
161
|
if (isHorizontal) {
|
|
162
|
+
const barValue = item.b ? item.o : item.x;
|
|
163
|
+
|
|
164
|
+
w = Canvas.calculateX(
|
|
165
|
+
barValue, minmaxX.graphMin, minmaxX.graphMax, xArea, -xZeroPosition,
|
|
166
|
+
);
|
|
167
|
+
|
|
155
168
|
if (item.b) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
w = Canvas.calculateX(item.x, minmaxX.graphMin, minmaxX.graphMax, xArea);
|
|
169
|
+
x = Canvas.calculateX(
|
|
170
|
+
item.b, minmaxX.graphMin, minmaxX.graphMax, xArea, xsp - xZeroPosition,
|
|
171
|
+
);
|
|
160
172
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
} else {
|
|
165
|
-
|
|
173
|
+
|
|
174
|
+
const minimumBarWidth = barValue > 0 ? -1 : 1;
|
|
175
|
+
w = barValue && Math.abs(w) === 0 ? minimumBarWidth : w;
|
|
176
|
+
} else {
|
|
177
|
+
const barValue = item.b ? item.o : item.y;
|
|
178
|
+
|
|
179
|
+
h = Canvas.calculateY(
|
|
180
|
+
barValue, minmaxY.graphMin, minmaxY.graphMax, yArea, -yZeroPosition,
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
if (item.b) {
|
|
184
|
+
y = Canvas.calculateY(
|
|
185
|
+
item.b, minmaxY.graphMin, minmaxY.graphMax, yArea, ysp - yZeroPosition,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const minimumBarHeight = barValue > 0 ? -1 : 1;
|
|
190
|
+
h = barValue && Math.abs(h) === 0 ? minimumBarHeight : h;
|
|
166
191
|
}
|
|
167
192
|
|
|
168
193
|
const barColor = item.dataColor || this.color;
|
|
169
|
-
|
|
170
194
|
const legendHitInfo = param?.legendHitInfo;
|
|
171
195
|
const selectLabelOption = param?.selectLabel?.option;
|
|
172
196
|
const selectItemOption = param?.selectItem?.option;
|
|
@@ -408,7 +432,7 @@ class Bar {
|
|
|
408
432
|
drawValueLabels({ context, data, positions, isHighlight, textColor, index }) {
|
|
409
433
|
const isHorizontal = this.isHorizontal;
|
|
410
434
|
const { fontSize, textColor: seriesTextColor, align, formatter, decimalPoint } = this.showValue;
|
|
411
|
-
const { x, y, w, h } = positions;
|
|
435
|
+
const { x: barX, y: barY, w: barWidth, h: barHeight } = positions;
|
|
412
436
|
const ctx = context;
|
|
413
437
|
|
|
414
438
|
ctx.save();
|
|
@@ -440,36 +464,40 @@ class Bar {
|
|
|
440
464
|
formattedTxt = Util.labelSignFormat(value, decimalPoint) ?? '';
|
|
441
465
|
}
|
|
442
466
|
|
|
467
|
+
const isNegativeValue = value < 0;
|
|
443
468
|
const textWidth = Math.round(ctx.measureText(formattedTxt).width);
|
|
444
|
-
const textHeight = fontSize
|
|
445
|
-
|
|
446
|
-
const
|
|
447
|
-
const
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
const
|
|
451
|
-
const
|
|
469
|
+
const textHeight = fontSize; // fontSize와 textHeight는 같을 수 없지만, 정확히 구할 필요 없음
|
|
470
|
+
|
|
471
|
+
const GAP = 10;
|
|
472
|
+
const minXPos = isNegativeValue ? barX - GAP : barX + GAP;
|
|
473
|
+
const minYPos = isNegativeValue ? barY + GAP : barY - GAP;
|
|
474
|
+
|
|
475
|
+
const centerXOnBar = barX + (barWidth / 2);
|
|
476
|
+
const centerYOnBar = isHighlight ? barY + (barHeight / 2) : barY - (barHeight / 2);
|
|
477
|
+
|
|
478
|
+
const drawableBarWidth = Math.abs(barWidth) - GAP;
|
|
479
|
+
const drawableBarHeight = Math.abs(barHeight) - GAP;
|
|
452
480
|
|
|
453
481
|
switch (align) {
|
|
454
482
|
case 'start': {
|
|
455
|
-
if (isHorizontal) {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
483
|
+
if (isHorizontal && textWidth < drawableBarWidth) {
|
|
484
|
+
const xPos = isNegativeValue ? minXPos - textWidth : minXPos;
|
|
485
|
+
ctx.fillText(formattedTxt, xPos, centerYOnBar);
|
|
486
|
+
} else if (!isHorizontal && textHeight < drawableBarHeight) {
|
|
487
|
+
const yPos = isNegativeValue
|
|
488
|
+
? barY + GAP
|
|
489
|
+
: barY - GAP;
|
|
490
|
+
ctx.fillText(formattedTxt, centerXOnBar, yPos);
|
|
461
491
|
}
|
|
462
492
|
|
|
463
493
|
break;
|
|
464
494
|
}
|
|
465
495
|
|
|
466
496
|
case 'center': {
|
|
467
|
-
if (isHorizontal) {
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
} else if (textHeight < heightFreeSpaceToDraw) {
|
|
472
|
-
ctx.fillText(formattedTxt, centerX, centerY);
|
|
497
|
+
if (isHorizontal && textWidth < drawableBarWidth) {
|
|
498
|
+
ctx.fillText(formattedTxt, centerXOnBar, centerYOnBar);
|
|
499
|
+
} else if (!isHorizontal && textHeight < drawableBarHeight) {
|
|
500
|
+
ctx.fillText(formattedTxt, centerXOnBar, barY + (barHeight / 2));
|
|
473
501
|
}
|
|
474
502
|
|
|
475
503
|
break;
|
|
@@ -482,9 +510,25 @@ class Bar {
|
|
|
482
510
|
}
|
|
483
511
|
|
|
484
512
|
if (isHorizontal) {
|
|
485
|
-
|
|
513
|
+
const minXOnChart = this.chartRect.x1 + this.labelOffset.left;
|
|
514
|
+
const maxXOnChart = this.chartRect.x2 - this.labelOffset.right;
|
|
515
|
+
|
|
516
|
+
if (isNegativeValue) {
|
|
517
|
+
const xPos = barX - GAP + barWidth - textWidth;
|
|
518
|
+
if (xPos > minXOnChart) {
|
|
519
|
+
ctx.fillText(formattedTxt, xPos, centerYOnBar);
|
|
520
|
+
}
|
|
521
|
+
} else {
|
|
522
|
+
const xPos = barX + GAP + barWidth;
|
|
523
|
+
if (xPos + textWidth < maxXOnChart) {
|
|
524
|
+
ctx.fillText(formattedTxt, xPos, centerYOnBar);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
486
527
|
} else {
|
|
487
|
-
|
|
528
|
+
const yPos = isNegativeValue
|
|
529
|
+
? barY + barHeight + GAP
|
|
530
|
+
: barY + barHeight - GAP;
|
|
531
|
+
ctx.fillText(formattedTxt, centerXOnBar, yPos);
|
|
488
532
|
}
|
|
489
533
|
|
|
490
534
|
break;
|
|
@@ -492,14 +536,21 @@ class Bar {
|
|
|
492
536
|
|
|
493
537
|
default:
|
|
494
538
|
case 'end': {
|
|
495
|
-
if (isHorizontal) {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
539
|
+
if (isHorizontal && textWidth < drawableBarWidth) {
|
|
540
|
+
const xPos = isNegativeValue
|
|
541
|
+
? barX + barWidth + GAP
|
|
542
|
+
: barX + barWidth - textWidth - GAP;
|
|
543
|
+
ctx.fillText(formattedTxt, xPos, centerYOnBar);
|
|
544
|
+
} else if (!isHorizontal) {
|
|
545
|
+
if (isNegativeValue) {
|
|
546
|
+
const yPos = barY + barHeight - GAP;
|
|
547
|
+
if (yPos > minYPos) {
|
|
548
|
+
ctx.fillText(formattedTxt, centerXOnBar, yPos);
|
|
549
|
+
}
|
|
550
|
+
} else if (textHeight < drawableBarHeight) {
|
|
551
|
+
const yPos = barY + barHeight + GAP;
|
|
552
|
+
ctx.fillText(formattedTxt, centerXOnBar, yPos);
|
|
499
553
|
}
|
|
500
|
-
} else if (textHeight < heightFreeSpaceToDraw) {
|
|
501
|
-
const yPos = y + h + textHeight;
|
|
502
|
-
ctx.fillText(formattedTxt, centerX, yPos >= minYPos ? minYPos : yPos);
|
|
503
554
|
}
|
|
504
555
|
|
|
505
556
|
break;
|
|
@@ -556,29 +607,48 @@ class Bar {
|
|
|
556
607
|
|
|
557
608
|
ctx.beginPath();
|
|
558
609
|
ctx.moveTo(x, y);
|
|
610
|
+
if (Math.abs(w) < r * 2) {
|
|
611
|
+
r = Math.abs(w) / 2;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
if (Math.abs(h) < r * 2) {
|
|
615
|
+
r = Math.abs(h) / 2;
|
|
616
|
+
}
|
|
559
617
|
|
|
560
618
|
if (isHorizontal) {
|
|
561
|
-
|
|
562
|
-
|
|
619
|
+
const isNegativeValue = w < 0;
|
|
620
|
+
if (isNegativeValue) {
|
|
621
|
+
w += r;
|
|
622
|
+
ctx.lineTo(x + w, y);
|
|
623
|
+
ctx.arcTo(x + w - r, y, x + w - r, y - r, r);
|
|
624
|
+
ctx.arcTo(x + w - r, y - h, x + w, y - h, r);
|
|
625
|
+
ctx.lineTo(x, y - h);
|
|
626
|
+
ctx.lineTo(x, y);
|
|
627
|
+
} else {
|
|
628
|
+
w -= r;
|
|
629
|
+
ctx.lineTo(x + w, y);
|
|
630
|
+
ctx.arcTo(x + w + r, y, x + w + r, y - r, r);
|
|
631
|
+
ctx.arcTo(x + w + r, y - h, x + w, y - h, r);
|
|
632
|
+
ctx.lineTo(x, y - h);
|
|
633
|
+
ctx.lineTo(x, y);
|
|
563
634
|
}
|
|
564
|
-
|
|
565
|
-
w -= r;
|
|
566
|
-
ctx.lineTo(x + w, y);
|
|
567
|
-
ctx.arcTo(x + w + r, y, x + w + r, y - r, r);
|
|
568
|
-
ctx.arcTo(x + w + r, y - h, x + w, y - h, r);
|
|
569
|
-
ctx.lineTo(x, y - h);
|
|
570
|
-
ctx.lineTo(x, y);
|
|
571
635
|
} else {
|
|
572
|
-
|
|
573
|
-
|
|
636
|
+
const isNegativeValue = h > 0;
|
|
637
|
+
if (isNegativeValue) {
|
|
638
|
+
h -= r;
|
|
639
|
+
ctx.lineTo(x + w, y);
|
|
640
|
+
ctx.lineTo(x + w, y + h);
|
|
641
|
+
ctx.arcTo(x + w, y + h + r, x - w + r, y + h + r, r);
|
|
642
|
+
ctx.arcTo(x, y + h + r, x, y + h, r);
|
|
643
|
+
ctx.lineTo(x, y);
|
|
644
|
+
} else {
|
|
645
|
+
h += r;
|
|
646
|
+
ctx.lineTo(x + w, y);
|
|
647
|
+
ctx.lineTo(x + w, y + h);
|
|
648
|
+
ctx.arcTo(x + w, y + h - r, x + w - r, y + h - r, r);
|
|
649
|
+
ctx.arcTo(x, y + h - r, x, y + h, r);
|
|
650
|
+
ctx.lineTo(x, y);
|
|
574
651
|
}
|
|
575
|
-
|
|
576
|
-
h += r;
|
|
577
|
-
ctx.lineTo(x + w, y);
|
|
578
|
-
ctx.lineTo(x + w, y + h);
|
|
579
|
-
ctx.arcTo(x + w, y + h - r, x + w - r, y + h - r, r);
|
|
580
|
-
ctx.arcTo(x, y + h - r, x, y + h, r);
|
|
581
|
-
ctx.lineTo(x, y);
|
|
582
652
|
}
|
|
583
653
|
|
|
584
654
|
ctx.fill();
|
|
@@ -104,8 +104,6 @@ class Line {
|
|
|
104
104
|
ctx.setLineDash(this.segments);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
const endPoint = chartRect.y2 - labelOffset.bottom;
|
|
108
|
-
|
|
109
107
|
const isLinearInterpolation = this.useLinearInterpolation();
|
|
110
108
|
|
|
111
109
|
let barAreaByCombo = 0;
|
|
@@ -127,6 +125,8 @@ class Line {
|
|
|
127
125
|
|
|
128
126
|
const getXPos = val => Canvas.calculateX(val, minmaxX.graphMin, minmaxX.graphMax, xArea, xsp);
|
|
129
127
|
const getYPos = val => Canvas.calculateY(val, minmaxY.graphMin, minmaxY.graphMax, yArea, ysp);
|
|
128
|
+
const includeNegativeValue = this.data.some(data => data.o < 0);
|
|
129
|
+
const endPoint = includeNegativeValue ? getYPos(0) : chartRect.y2 - labelOffset.bottom;
|
|
130
130
|
|
|
131
131
|
// draw line
|
|
132
132
|
let prevValid;
|
|
@@ -183,9 +183,10 @@ class Line {
|
|
|
183
183
|
}
|
|
184
184
|
});
|
|
185
185
|
const gradient = ctx.createLinearGradient(0, chartRect.y2, 0, maxValueYPos);
|
|
186
|
-
|
|
186
|
+
const mainGradientColor = extent.opacity < 1 ? fillColor : mainColor;
|
|
187
|
+
gradient.addColorStop(0, includeNegativeValue ? mainGradientColor : fillColor);
|
|
187
188
|
gradient.addColorStop(0.5, fillColor);
|
|
188
|
-
gradient.addColorStop(1,
|
|
189
|
+
gradient.addColorStop(1, mainGradientColor);
|
|
189
190
|
|
|
190
191
|
ctx.fillStyle = gradient;
|
|
191
192
|
} else {
|
|
@@ -242,7 +243,7 @@ class Line {
|
|
|
242
243
|
for (let jx = endIndex; jx >= startIndex; jx--) {
|
|
243
244
|
const nextData = this.data[jx];
|
|
244
245
|
const xp = getXPos(nextData.x);
|
|
245
|
-
const bp = getYPos(nextData.b) ??
|
|
246
|
+
const bp = getYPos(nextData.b) ?? getYPos(0);
|
|
246
247
|
ctx.lineTo(xp, bp);
|
|
247
248
|
}
|
|
248
249
|
|
|
@@ -27,8 +27,9 @@ const modules = {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
if (labelTipOpt.use && labelTipOpt.showTip) {
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
isExistSelectedLabel = opt.type === 'heatMap'
|
|
31
|
+
? this.drawLabelTipForHeatMap()
|
|
32
|
+
: this.drawTipForSelectedLabel();
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
const executeDrawIndicator = (tipOpt) => {
|
|
@@ -283,9 +284,10 @@ const modules = {
|
|
|
283
284
|
|
|
284
285
|
/**
|
|
285
286
|
* Draw Selected Label Tip
|
|
287
|
+
* none Text
|
|
286
288
|
* @returns {boolean} Whether drew at least one tip
|
|
287
289
|
*/
|
|
288
|
-
|
|
290
|
+
drawTipForSelectedLabel() {
|
|
289
291
|
const opt = this.options;
|
|
290
292
|
const isHorizontal = !!opt.horizontal;
|
|
291
293
|
const labelTipOpt = opt.selectLabel;
|
|
@@ -305,7 +307,7 @@ const modules = {
|
|
|
305
307
|
};
|
|
306
308
|
const labelAxes = isHorizontal ? this.axesY[0] : this.axesX[0];
|
|
307
309
|
const valueAxes = isHorizontal ? this.axesX[0] : this.axesY[0];
|
|
308
|
-
const
|
|
310
|
+
const valueAxesSteps = isHorizontal ? this.axesSteps.x[0] : this.axesSteps.y[0];
|
|
309
311
|
const valuePositionCalcFunction = isHorizontal ? Canvas.calculateX : Canvas.calculateY;
|
|
310
312
|
const labelPositionCalcFunction = isHorizontal ? Canvas.calculateY : Canvas.calculateX;
|
|
311
313
|
const scrollbarOpt = isHorizontal ? this.scrollbar.y : this.scrollbar.x;
|
|
@@ -323,8 +325,8 @@ const modules = {
|
|
|
323
325
|
.some(sId => this.seriesList[sId].isExistGrp && !this.seriesList[sId].isOverlapping);
|
|
324
326
|
const groups = this.data.groups?.[0] ?? [];
|
|
325
327
|
|
|
326
|
-
let
|
|
327
|
-
let
|
|
328
|
+
let labelPos;
|
|
329
|
+
let dataPos;
|
|
328
330
|
let value;
|
|
329
331
|
let labelStartPoint;
|
|
330
332
|
let labelEndPoint;
|
|
@@ -357,21 +359,38 @@ const modules = {
|
|
|
357
359
|
}
|
|
358
360
|
|
|
359
361
|
data.forEach((selectedData, i) => {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
362
|
+
value = valueAxesSteps.graphMax;
|
|
363
|
+
|
|
364
|
+
if (!labelTipOpt.fixedPosTop) {
|
|
365
|
+
if (isExistGrp) {
|
|
366
|
+
const positiveSum = visibleSeries?.reduce((ac, sId) => (
|
|
367
|
+
groups.includes(sId) && (selectedData[sId]?.value ?? selectedData[sId]) > 0
|
|
368
|
+
? ac + (selectedData[sId]?.value ?? selectedData[sId])
|
|
369
|
+
: ac), 0);
|
|
370
|
+
|
|
371
|
+
const nonGroupValues = visibleSeries
|
|
372
|
+
?.filter(sId => !groups.includes(sId))
|
|
373
|
+
?.map(sId => selectedData[sId]?.value ?? selectedData[sId]) ?? [];
|
|
374
|
+
|
|
375
|
+
const maxNonGroupValue = nonGroupValues?.length > 0
|
|
376
|
+
? nonGroupValues.reduce((max, val) => Math.max(max, val ?? -Infinity), -Infinity)
|
|
377
|
+
: -Infinity;
|
|
378
|
+
|
|
379
|
+
value = positiveSum > 0
|
|
380
|
+
? Math.max(maxNonGroupValue, positiveSum)
|
|
381
|
+
: Math.max(maxNonGroupValue, 0);
|
|
382
|
+
} else if (visibleSeries.length) {
|
|
383
|
+
const visibleValue = visibleSeries
|
|
384
|
+
.map(sId => selectedData[sId]?.value ?? selectedData[sId]);
|
|
385
|
+
|
|
386
|
+
const maxValue = visibleValue.length > 0
|
|
387
|
+
? visibleValue.reduce((max, val) => Math.max(max, val ?? -Infinity), -Infinity)
|
|
388
|
+
: -Infinity;
|
|
389
|
+
|
|
390
|
+
value = maxValue > 0 || this.options.type !== 'bar'
|
|
391
|
+
? maxValue
|
|
392
|
+
: 0;
|
|
393
|
+
}
|
|
375
394
|
}
|
|
376
395
|
|
|
377
396
|
if (labelAxes.labels) {
|
|
@@ -381,9 +400,9 @@ const modules = {
|
|
|
381
400
|
|
|
382
401
|
const labelIndex = dataIndex[i] - startIndex;
|
|
383
402
|
const labelCenter = Math.round(labelStartPoint + (labelGap * labelIndex));
|
|
384
|
-
|
|
403
|
+
labelPos = labelCenter + (labelGap / 2);
|
|
385
404
|
} else {
|
|
386
|
-
|
|
405
|
+
labelPos = labelPositionCalcFunction(
|
|
387
406
|
label[i],
|
|
388
407
|
graphX.graphMin,
|
|
389
408
|
graphX.graphMax,
|
|
@@ -391,18 +410,19 @@ const modules = {
|
|
|
391
410
|
aPos.x1 + (sizeObj.comboOffset / 2),
|
|
392
411
|
);
|
|
393
412
|
}
|
|
394
|
-
|
|
413
|
+
|
|
414
|
+
dataPos = valuePositionCalcFunction(
|
|
395
415
|
value,
|
|
396
|
-
|
|
397
|
-
|
|
416
|
+
valueAxesSteps.graphMin,
|
|
417
|
+
valueAxesSteps.graphMax,
|
|
398
418
|
valueSpace,
|
|
399
|
-
valueStartPoint
|
|
400
|
-
|
|
419
|
+
valueStartPoint,
|
|
420
|
+
) + offset;
|
|
401
421
|
|
|
402
422
|
this.showTip({
|
|
403
423
|
context: this.bufferCtx,
|
|
404
|
-
x: isHorizontal ?
|
|
405
|
-
y: isHorizontal ?
|
|
424
|
+
x: isHorizontal ? dataPos : labelPos,
|
|
425
|
+
y: isHorizontal ? labelPos : dataPos,
|
|
406
426
|
opt: labelTipOpt,
|
|
407
427
|
isSamePos: false,
|
|
408
428
|
});
|
|
@@ -504,10 +524,11 @@ const modules = {
|
|
|
504
524
|
}
|
|
505
525
|
} else if (isHorizontal) {
|
|
506
526
|
gp = Canvas.calculateX(value, graphX.graphMin, graphX.graphMax, xArea, xsp);
|
|
507
|
-
gp
|
|
527
|
+
gp = value < 0 ? gp - offset : gp + offset;
|
|
508
528
|
} else {
|
|
509
|
-
|
|
510
|
-
gp
|
|
529
|
+
const adjustedValue = type === 'bar' && value < 0 ? 0 : value;
|
|
530
|
+
gp = Canvas.calculateY(adjustedValue, graphY.graphMin, graphY.graphMax, yArea, ysp);
|
|
531
|
+
gp = adjustedValue < 0 ? gp + offset : gp - offset;
|
|
511
532
|
}
|
|
512
533
|
|
|
513
534
|
let maxTipType = 'center';
|
|
@@ -541,6 +562,7 @@ const modules = {
|
|
|
541
562
|
borderRadius,
|
|
542
563
|
text,
|
|
543
564
|
textStyle,
|
|
565
|
+
isNegative: value < 0,
|
|
544
566
|
});
|
|
545
567
|
}
|
|
546
568
|
|
|
@@ -563,15 +585,24 @@ const modules = {
|
|
|
563
585
|
*/
|
|
564
586
|
showTextTip(param) {
|
|
565
587
|
const isHorizontal = !!this.options.horizontal;
|
|
566
|
-
const {
|
|
588
|
+
const {
|
|
589
|
+
type, width, height, x, y, arrowSize, borderRadius, text, opt, textStyle, isNegative,
|
|
590
|
+
} = param;
|
|
567
591
|
|
|
568
592
|
const ctx = param.context;
|
|
569
593
|
|
|
570
|
-
|
|
571
|
-
|
|
594
|
+
let sx = x - (width / 2);
|
|
595
|
+
let ex = x + (width / 2);
|
|
572
596
|
const sy = y - height;
|
|
573
597
|
const ey = y;
|
|
574
598
|
|
|
599
|
+
if (isNegative) {
|
|
600
|
+
if (isHorizontal) {
|
|
601
|
+
sx = x - (width / 2) - width;
|
|
602
|
+
ex = x - (width / 2);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
575
606
|
ctx.save();
|
|
576
607
|
ctx.font = textStyle;
|
|
577
608
|
|
|
@@ -581,30 +612,8 @@ const modules = {
|
|
|
581
612
|
ctx.beginPath();
|
|
582
613
|
ctx.moveTo(sx + borderRadius, sy);
|
|
583
614
|
ctx.quadraticCurveTo(sx, sy, sx, sy + borderRadius);
|
|
584
|
-
|
|
585
|
-
if (isHorizontal) {
|
|
586
|
-
ctx.lineTo(sx, sy + borderRadius + (arrowSize / 2));
|
|
587
|
-
ctx.lineTo(sx - arrowSize, ey - (height / 2));
|
|
588
|
-
ctx.lineTo(sx, ey - borderRadius - (arrowSize / 2));
|
|
589
|
-
}
|
|
590
|
-
|
|
591
615
|
ctx.lineTo(sx, ey - borderRadius);
|
|
592
616
|
ctx.quadraticCurveTo(sx, ey, sx + borderRadius, ey);
|
|
593
|
-
|
|
594
|
-
if (!isHorizontal) {
|
|
595
|
-
if (type === 'left') {
|
|
596
|
-
ctx.lineTo(sx + borderRadius + arrowSize, ey + arrowSize);
|
|
597
|
-
ctx.lineTo(sx + borderRadius + (arrowSize * 2), ey);
|
|
598
|
-
} else if (type === 'right') {
|
|
599
|
-
ctx.lineTo(ex - (arrowSize * 2) - borderRadius, ey);
|
|
600
|
-
ctx.lineTo(ex - arrowSize - borderRadius, ey + arrowSize);
|
|
601
|
-
} else {
|
|
602
|
-
ctx.lineTo(x - arrowSize, ey);
|
|
603
|
-
ctx.lineTo(x, ey + arrowSize);
|
|
604
|
-
ctx.lineTo(x + arrowSize, ey);
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
|
|
608
617
|
ctx.lineTo(ex - borderRadius, ey);
|
|
609
618
|
ctx.quadraticCurveTo(ex, ey, ex, ey - borderRadius);
|
|
610
619
|
ctx.lineTo(ex, sy + borderRadius);
|
|
@@ -612,13 +621,64 @@ const modules = {
|
|
|
612
621
|
ctx.lineTo(sx + borderRadius, sy);
|
|
613
622
|
ctx.closePath();
|
|
614
623
|
ctx.fill();
|
|
624
|
+
|
|
625
|
+
// draw arrow
|
|
626
|
+
ctx.beginPath();
|
|
627
|
+
if (isHorizontal) {
|
|
628
|
+
if (isNegative) {
|
|
629
|
+
ctx.moveTo(ex, ey);
|
|
630
|
+
ctx.lineTo(ex, sy + borderRadius + (arrowSize / 2));
|
|
631
|
+
ctx.lineTo(ex + arrowSize, ey - (height / 2));
|
|
632
|
+
ctx.lineTo(ex, ey - borderRadius - (arrowSize / 2));
|
|
633
|
+
} else {
|
|
634
|
+
ctx.moveTo(sx, sy);
|
|
635
|
+
ctx.lineTo(sx, sy + borderRadius + (arrowSize / 2));
|
|
636
|
+
ctx.lineTo(sx - arrowSize, ey - (height / 2));
|
|
637
|
+
ctx.lineTo(sx, ey - borderRadius - (arrowSize / 2));
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
ctx.closePath();
|
|
641
|
+
ctx.fill();
|
|
642
|
+
} else {
|
|
643
|
+
if (isNegative) {
|
|
644
|
+
if (type === 'left') {
|
|
645
|
+
ctx.lineTo(sx + borderRadius + arrowSize, ey + arrowSize);
|
|
646
|
+
ctx.lineTo(sx + borderRadius + (arrowSize * 2), ey);
|
|
647
|
+
} else if (type === 'right') {
|
|
648
|
+
ctx.lineTo(ex - (arrowSize * 2) - borderRadius, ey);
|
|
649
|
+
ctx.lineTo(ex - arrowSize - borderRadius, ey + arrowSize);
|
|
650
|
+
} else {
|
|
651
|
+
ctx.lineTo(x - arrowSize, ey);
|
|
652
|
+
ctx.lineTo(x, ey + arrowSize);
|
|
653
|
+
ctx.lineTo(x + arrowSize, ey);
|
|
654
|
+
}
|
|
655
|
+
} else if (!isNegative) {
|
|
656
|
+
if (type === 'left') {
|
|
657
|
+
ctx.moveTo(sx, sy);
|
|
658
|
+
ctx.lineTo(sx + borderRadius + arrowSize, ey + arrowSize);
|
|
659
|
+
ctx.lineTo(sx + borderRadius + (arrowSize * 2), ey);
|
|
660
|
+
} else if (type === 'right') {
|
|
661
|
+
ctx.moveTo(ex, sy);
|
|
662
|
+
ctx.lineTo(ex - (arrowSize * 2) - borderRadius, ey);
|
|
663
|
+
ctx.lineTo(ex - arrowSize - borderRadius, ey + arrowSize);
|
|
664
|
+
} else {
|
|
665
|
+
ctx.lineTo(x - arrowSize, ey);
|
|
666
|
+
ctx.lineTo(x, ey + arrowSize);
|
|
667
|
+
ctx.lineTo(x + arrowSize, ey);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
ctx.closePath();
|
|
672
|
+
ctx.fill();
|
|
673
|
+
}
|
|
674
|
+
|
|
615
675
|
ctx.restore();
|
|
616
676
|
ctx.save();
|
|
617
677
|
ctx.font = textStyle;
|
|
618
678
|
ctx.fillStyle = opt.tipTextColor ?? opt.tipStyle.textColor;
|
|
619
679
|
ctx.textBaseline = 'middle';
|
|
620
680
|
ctx.textAlign = 'center';
|
|
621
|
-
ctx.fillText(`${text}`,
|
|
681
|
+
ctx.fillText(`${text}`, sx + (width / 2), sy + (height / 2));
|
|
622
682
|
ctx.restore();
|
|
623
683
|
},
|
|
624
684
|
|
|
@@ -640,7 +700,7 @@ const modules = {
|
|
|
640
700
|
ctx.beginPath();
|
|
641
701
|
ctx.moveTo(x, cy);
|
|
642
702
|
if (isHorizontal) {
|
|
643
|
-
|
|
703
|
+
ctx.lineTo(x + 6, cy - 6);
|
|
644
704
|
ctx.lineTo(x + 6, cy + 6);
|
|
645
705
|
} else {
|
|
646
706
|
ctx.lineTo(x + 6, cy - 6);
|
|
@@ -160,25 +160,29 @@ export default {
|
|
|
160
160
|
return value;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
const isNegative = value < 0;
|
|
164
|
+
const absValue = Math.abs(value);
|
|
165
|
+
|
|
163
166
|
const assignLabelWith = (v, target, lb) => {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
167
|
+
const result = v % target === 0
|
|
168
|
+
? `${(v / target).toFixed(decimalPoint)}${lb}`
|
|
169
|
+
: `${(v / target).toFixed(1)}${lb}`;
|
|
170
|
+
|
|
171
|
+
return isNegative ? `-${result}` : result;
|
|
168
172
|
};
|
|
169
173
|
|
|
170
|
-
if (
|
|
171
|
-
label = assignLabelWith(
|
|
172
|
-
} else if (
|
|
173
|
-
label = assignLabelWith(
|
|
174
|
-
} else if (
|
|
175
|
-
label = assignLabelWith(
|
|
176
|
-
} else if (
|
|
177
|
-
label = assignLabelWith(
|
|
178
|
-
} else if (
|
|
179
|
-
label = assignLabelWith(
|
|
174
|
+
if (absValue >= quad) {
|
|
175
|
+
label = assignLabelWith(absValue, quad, 'P');
|
|
176
|
+
} else if (absValue >= trill) {
|
|
177
|
+
label = assignLabelWith(absValue, trill, 'T');
|
|
178
|
+
} else if (absValue >= billi) {
|
|
179
|
+
label = assignLabelWith(absValue, billi, 'G');
|
|
180
|
+
} else if (absValue >= milli) {
|
|
181
|
+
label = assignLabelWith(absValue, milli, 'M');
|
|
182
|
+
} else if (absValue >= killo) {
|
|
183
|
+
label = assignLabelWith(absValue, 1000, 'K');
|
|
180
184
|
} else {
|
|
181
|
-
label = value.toFixed(decimalPoint);
|
|
185
|
+
label = isNegative ? `-${absValue.toFixed(decimalPoint)}` : value.toFixed(decimalPoint);
|
|
182
186
|
}
|
|
183
187
|
|
|
184
188
|
return label;
|