hyperprop-charting-library 0.1.103 → 0.1.105
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.
|
@@ -75,7 +75,11 @@ var DEFAULT_CROSSHAIR_OPTIONS = {
|
|
|
75
75
|
priceActionButtonSize: 16,
|
|
76
76
|
priceActionButtonGap: 4,
|
|
77
77
|
priceActionButtonRounded: true,
|
|
78
|
-
priceActionButtonBorderRadius: 8
|
|
78
|
+
priceActionButtonBorderRadius: 8,
|
|
79
|
+
sideHintLeft: "",
|
|
80
|
+
sideHintRight: "",
|
|
81
|
+
sideHintLeftColor: "#26a69a",
|
|
82
|
+
sideHintRightColor: "#ef5350"
|
|
79
83
|
};
|
|
80
84
|
var DEFAULT_WATERMARK_OPTIONS = {
|
|
81
85
|
visible: false,
|
|
@@ -1292,10 +1296,19 @@ function createChart(element, options = {}) {
|
|
|
1292
1296
|
}
|
|
1293
1297
|
return Math.round(price / tickSize) * tickSize;
|
|
1294
1298
|
};
|
|
1299
|
+
const groupThousands = (value, decimals) => {
|
|
1300
|
+
const negative = value < 0;
|
|
1301
|
+
const fixed = Math.abs(value).toFixed(decimals);
|
|
1302
|
+
const dot = fixed.indexOf(".");
|
|
1303
|
+
const intPart = dot === -1 ? fixed : fixed.slice(0, dot);
|
|
1304
|
+
const decPart = dot === -1 ? "" : fixed.slice(dot);
|
|
1305
|
+
const grouped = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1306
|
+
return `${negative ? "-" : ""}${grouped}${decPart}`;
|
|
1307
|
+
};
|
|
1295
1308
|
const formatPrice = (price) => {
|
|
1296
1309
|
const rounded = quantizeToTickSize(price);
|
|
1297
1310
|
const decimals = getDisplayPriceDecimals();
|
|
1298
|
-
return rounded
|
|
1311
|
+
return groupThousands(rounded, decimals);
|
|
1299
1312
|
};
|
|
1300
1313
|
const roundToPricePrecision = (price) => {
|
|
1301
1314
|
const rounded = quantizeToTickSize(price);
|
|
@@ -1333,7 +1346,7 @@ function createChart(element, options = {}) {
|
|
|
1333
1346
|
}
|
|
1334
1347
|
const observedDigits = maxAbsPrice >= 1 ? Math.floor(Math.log10(maxAbsPrice)) + 1 : 1;
|
|
1335
1348
|
const integerDigits = Math.max(configuredDigits, observedDigits);
|
|
1336
|
-
const integerPart = "8".repeat(integerDigits);
|
|
1349
|
+
const integerPart = "8".repeat(integerDigits).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1337
1350
|
const decimalPart = decimals > 0 ? `.${"8".repeat(decimals)}` : "";
|
|
1338
1351
|
return `${integerPart}${decimalPart}`;
|
|
1339
1352
|
};
|
|
@@ -3008,6 +3021,25 @@ function createChart(element, options = {}) {
|
|
|
3008
3021
|
}
|
|
3009
3022
|
ctx.restore();
|
|
3010
3023
|
}
|
|
3024
|
+
if (crosshair.sideHintLeft || crosshair.sideHintRight) {
|
|
3025
|
+
ctx.save();
|
|
3026
|
+
ctx.font = `600 11px ${mergedOptions.fontFamily}`;
|
|
3027
|
+
ctx.textBaseline = "middle";
|
|
3028
|
+
ctx.setLineDash([]);
|
|
3029
|
+
const hintY = clamp(cy - 14, chartTop + 8, chartBottom - 8);
|
|
3030
|
+
const hintGap = 8;
|
|
3031
|
+
if (crosshair.sideHintLeft) {
|
|
3032
|
+
ctx.fillStyle = crosshair.sideHintLeftColor;
|
|
3033
|
+
ctx.textAlign = "right";
|
|
3034
|
+
ctx.fillText(crosshair.sideHintLeft, cx - hintGap, hintY);
|
|
3035
|
+
}
|
|
3036
|
+
if (crosshair.sideHintRight) {
|
|
3037
|
+
ctx.fillStyle = crosshair.sideHintRightColor;
|
|
3038
|
+
ctx.textAlign = "left";
|
|
3039
|
+
ctx.fillText(crosshair.sideHintRight, cx + hintGap, hintY);
|
|
3040
|
+
}
|
|
3041
|
+
ctx.restore();
|
|
3042
|
+
}
|
|
3011
3043
|
}
|
|
3012
3044
|
ctx.restore();
|
|
3013
3045
|
const positionAxisGutter = Math.max(0, width - chartRight);
|
|
@@ -3432,16 +3464,18 @@ function createChart(element, options = {}) {
|
|
|
3432
3464
|
ctx.font = prevFont;
|
|
3433
3465
|
}
|
|
3434
3466
|
}
|
|
3467
|
+
const axisStepMs = getTimeStepMs();
|
|
3468
|
+
const axisIntraday = axisStepMs > 0 && axisStepMs < 24 * 60 * 60 * 1e3;
|
|
3469
|
+
let prevAxisTickTime = null;
|
|
3435
3470
|
for (let index = tickStartIndex; index <= visibleTickEnd; index += xStep) {
|
|
3436
3471
|
const tickTime = getTimeForIndex(index);
|
|
3437
3472
|
if (!tickTime) {
|
|
3438
3473
|
continue;
|
|
3439
3474
|
}
|
|
3440
3475
|
const x = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
3441
|
-
const
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
});
|
|
3476
|
+
const isNewDay = !prevAxisTickTime || prevAxisTickTime.getDate() !== tickTime.getDate() || prevAxisTickTime.getMonth() !== tickTime.getMonth() || prevAxisTickTime.getFullYear() !== tickTime.getFullYear();
|
|
3477
|
+
const timeLabel = axisIntraday && !isNewDay ? tickTime.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", hour12: false }) : tickTime.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
3478
|
+
prevAxisTickTime = tickTime;
|
|
3445
3479
|
const prevFont = ctx.font;
|
|
3446
3480
|
ctx.font = `${xAxisFontSize}px ${mergedOptions.fontFamily}`;
|
|
3447
3481
|
drawText(timeLabel, x, fullChartBottom + 8, "center", "top", xAxis.textColor);
|
|
@@ -241,6 +241,10 @@ interface CrosshairOptions {
|
|
|
241
241
|
priceActionButtonGap?: number;
|
|
242
242
|
priceActionButtonRounded?: boolean;
|
|
243
243
|
priceActionButtonBorderRadius?: number;
|
|
244
|
+
sideHintLeft?: string;
|
|
245
|
+
sideHintRight?: string;
|
|
246
|
+
sideHintLeftColor?: string;
|
|
247
|
+
sideHintRightColor?: string;
|
|
244
248
|
}
|
|
245
249
|
interface WatermarkOptions {
|
|
246
250
|
visible?: boolean;
|
|
@@ -49,7 +49,11 @@ var DEFAULT_CROSSHAIR_OPTIONS = {
|
|
|
49
49
|
priceActionButtonSize: 16,
|
|
50
50
|
priceActionButtonGap: 4,
|
|
51
51
|
priceActionButtonRounded: true,
|
|
52
|
-
priceActionButtonBorderRadius: 8
|
|
52
|
+
priceActionButtonBorderRadius: 8,
|
|
53
|
+
sideHintLeft: "",
|
|
54
|
+
sideHintRight: "",
|
|
55
|
+
sideHintLeftColor: "#26a69a",
|
|
56
|
+
sideHintRightColor: "#ef5350"
|
|
53
57
|
};
|
|
54
58
|
var DEFAULT_WATERMARK_OPTIONS = {
|
|
55
59
|
visible: false,
|
|
@@ -1266,10 +1270,19 @@ function createChart(element, options = {}) {
|
|
|
1266
1270
|
}
|
|
1267
1271
|
return Math.round(price / tickSize) * tickSize;
|
|
1268
1272
|
};
|
|
1273
|
+
const groupThousands = (value, decimals) => {
|
|
1274
|
+
const negative = value < 0;
|
|
1275
|
+
const fixed = Math.abs(value).toFixed(decimals);
|
|
1276
|
+
const dot = fixed.indexOf(".");
|
|
1277
|
+
const intPart = dot === -1 ? fixed : fixed.slice(0, dot);
|
|
1278
|
+
const decPart = dot === -1 ? "" : fixed.slice(dot);
|
|
1279
|
+
const grouped = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1280
|
+
return `${negative ? "-" : ""}${grouped}${decPart}`;
|
|
1281
|
+
};
|
|
1269
1282
|
const formatPrice = (price) => {
|
|
1270
1283
|
const rounded = quantizeToTickSize(price);
|
|
1271
1284
|
const decimals = getDisplayPriceDecimals();
|
|
1272
|
-
return rounded
|
|
1285
|
+
return groupThousands(rounded, decimals);
|
|
1273
1286
|
};
|
|
1274
1287
|
const roundToPricePrecision = (price) => {
|
|
1275
1288
|
const rounded = quantizeToTickSize(price);
|
|
@@ -1307,7 +1320,7 @@ function createChart(element, options = {}) {
|
|
|
1307
1320
|
}
|
|
1308
1321
|
const observedDigits = maxAbsPrice >= 1 ? Math.floor(Math.log10(maxAbsPrice)) + 1 : 1;
|
|
1309
1322
|
const integerDigits = Math.max(configuredDigits, observedDigits);
|
|
1310
|
-
const integerPart = "8".repeat(integerDigits);
|
|
1323
|
+
const integerPart = "8".repeat(integerDigits).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1311
1324
|
const decimalPart = decimals > 0 ? `.${"8".repeat(decimals)}` : "";
|
|
1312
1325
|
return `${integerPart}${decimalPart}`;
|
|
1313
1326
|
};
|
|
@@ -2982,6 +2995,25 @@ function createChart(element, options = {}) {
|
|
|
2982
2995
|
}
|
|
2983
2996
|
ctx.restore();
|
|
2984
2997
|
}
|
|
2998
|
+
if (crosshair.sideHintLeft || crosshair.sideHintRight) {
|
|
2999
|
+
ctx.save();
|
|
3000
|
+
ctx.font = `600 11px ${mergedOptions.fontFamily}`;
|
|
3001
|
+
ctx.textBaseline = "middle";
|
|
3002
|
+
ctx.setLineDash([]);
|
|
3003
|
+
const hintY = clamp(cy - 14, chartTop + 8, chartBottom - 8);
|
|
3004
|
+
const hintGap = 8;
|
|
3005
|
+
if (crosshair.sideHintLeft) {
|
|
3006
|
+
ctx.fillStyle = crosshair.sideHintLeftColor;
|
|
3007
|
+
ctx.textAlign = "right";
|
|
3008
|
+
ctx.fillText(crosshair.sideHintLeft, cx - hintGap, hintY);
|
|
3009
|
+
}
|
|
3010
|
+
if (crosshair.sideHintRight) {
|
|
3011
|
+
ctx.fillStyle = crosshair.sideHintRightColor;
|
|
3012
|
+
ctx.textAlign = "left";
|
|
3013
|
+
ctx.fillText(crosshair.sideHintRight, cx + hintGap, hintY);
|
|
3014
|
+
}
|
|
3015
|
+
ctx.restore();
|
|
3016
|
+
}
|
|
2985
3017
|
}
|
|
2986
3018
|
ctx.restore();
|
|
2987
3019
|
const positionAxisGutter = Math.max(0, width - chartRight);
|
|
@@ -3406,16 +3438,18 @@ function createChart(element, options = {}) {
|
|
|
3406
3438
|
ctx.font = prevFont;
|
|
3407
3439
|
}
|
|
3408
3440
|
}
|
|
3441
|
+
const axisStepMs = getTimeStepMs();
|
|
3442
|
+
const axisIntraday = axisStepMs > 0 && axisStepMs < 24 * 60 * 60 * 1e3;
|
|
3443
|
+
let prevAxisTickTime = null;
|
|
3409
3444
|
for (let index = tickStartIndex; index <= visibleTickEnd; index += xStep) {
|
|
3410
3445
|
const tickTime = getTimeForIndex(index);
|
|
3411
3446
|
if (!tickTime) {
|
|
3412
3447
|
continue;
|
|
3413
3448
|
}
|
|
3414
3449
|
const x = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
3415
|
-
const
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
});
|
|
3450
|
+
const isNewDay = !prevAxisTickTime || prevAxisTickTime.getDate() !== tickTime.getDate() || prevAxisTickTime.getMonth() !== tickTime.getMonth() || prevAxisTickTime.getFullYear() !== tickTime.getFullYear();
|
|
3451
|
+
const timeLabel = axisIntraday && !isNewDay ? tickTime.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", hour12: false }) : tickTime.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
3452
|
+
prevAxisTickTime = tickTime;
|
|
3419
3453
|
const prevFont = ctx.font;
|
|
3420
3454
|
ctx.font = `${xAxisFontSize}px ${mergedOptions.fontFamily}`;
|
|
3421
3455
|
drawText(timeLabel, x, fullChartBottom + 8, "center", "top", xAxis.textColor);
|
package/dist/index.cjs
CHANGED
|
@@ -75,7 +75,11 @@ var DEFAULT_CROSSHAIR_OPTIONS = {
|
|
|
75
75
|
priceActionButtonSize: 16,
|
|
76
76
|
priceActionButtonGap: 4,
|
|
77
77
|
priceActionButtonRounded: true,
|
|
78
|
-
priceActionButtonBorderRadius: 8
|
|
78
|
+
priceActionButtonBorderRadius: 8,
|
|
79
|
+
sideHintLeft: "",
|
|
80
|
+
sideHintRight: "",
|
|
81
|
+
sideHintLeftColor: "#26a69a",
|
|
82
|
+
sideHintRightColor: "#ef5350"
|
|
79
83
|
};
|
|
80
84
|
var DEFAULT_WATERMARK_OPTIONS = {
|
|
81
85
|
visible: false,
|
|
@@ -1292,10 +1296,19 @@ function createChart(element, options = {}) {
|
|
|
1292
1296
|
}
|
|
1293
1297
|
return Math.round(price / tickSize) * tickSize;
|
|
1294
1298
|
};
|
|
1299
|
+
const groupThousands = (value, decimals) => {
|
|
1300
|
+
const negative = value < 0;
|
|
1301
|
+
const fixed = Math.abs(value).toFixed(decimals);
|
|
1302
|
+
const dot = fixed.indexOf(".");
|
|
1303
|
+
const intPart = dot === -1 ? fixed : fixed.slice(0, dot);
|
|
1304
|
+
const decPart = dot === -1 ? "" : fixed.slice(dot);
|
|
1305
|
+
const grouped = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1306
|
+
return `${negative ? "-" : ""}${grouped}${decPart}`;
|
|
1307
|
+
};
|
|
1295
1308
|
const formatPrice = (price) => {
|
|
1296
1309
|
const rounded = quantizeToTickSize(price);
|
|
1297
1310
|
const decimals = getDisplayPriceDecimals();
|
|
1298
|
-
return rounded
|
|
1311
|
+
return groupThousands(rounded, decimals);
|
|
1299
1312
|
};
|
|
1300
1313
|
const roundToPricePrecision = (price) => {
|
|
1301
1314
|
const rounded = quantizeToTickSize(price);
|
|
@@ -1333,7 +1346,7 @@ function createChart(element, options = {}) {
|
|
|
1333
1346
|
}
|
|
1334
1347
|
const observedDigits = maxAbsPrice >= 1 ? Math.floor(Math.log10(maxAbsPrice)) + 1 : 1;
|
|
1335
1348
|
const integerDigits = Math.max(configuredDigits, observedDigits);
|
|
1336
|
-
const integerPart = "8".repeat(integerDigits);
|
|
1349
|
+
const integerPart = "8".repeat(integerDigits).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1337
1350
|
const decimalPart = decimals > 0 ? `.${"8".repeat(decimals)}` : "";
|
|
1338
1351
|
return `${integerPart}${decimalPart}`;
|
|
1339
1352
|
};
|
|
@@ -3008,6 +3021,25 @@ function createChart(element, options = {}) {
|
|
|
3008
3021
|
}
|
|
3009
3022
|
ctx.restore();
|
|
3010
3023
|
}
|
|
3024
|
+
if (crosshair.sideHintLeft || crosshair.sideHintRight) {
|
|
3025
|
+
ctx.save();
|
|
3026
|
+
ctx.font = `600 11px ${mergedOptions.fontFamily}`;
|
|
3027
|
+
ctx.textBaseline = "middle";
|
|
3028
|
+
ctx.setLineDash([]);
|
|
3029
|
+
const hintY = clamp(cy - 14, chartTop + 8, chartBottom - 8);
|
|
3030
|
+
const hintGap = 8;
|
|
3031
|
+
if (crosshair.sideHintLeft) {
|
|
3032
|
+
ctx.fillStyle = crosshair.sideHintLeftColor;
|
|
3033
|
+
ctx.textAlign = "right";
|
|
3034
|
+
ctx.fillText(crosshair.sideHintLeft, cx - hintGap, hintY);
|
|
3035
|
+
}
|
|
3036
|
+
if (crosshair.sideHintRight) {
|
|
3037
|
+
ctx.fillStyle = crosshair.sideHintRightColor;
|
|
3038
|
+
ctx.textAlign = "left";
|
|
3039
|
+
ctx.fillText(crosshair.sideHintRight, cx + hintGap, hintY);
|
|
3040
|
+
}
|
|
3041
|
+
ctx.restore();
|
|
3042
|
+
}
|
|
3011
3043
|
}
|
|
3012
3044
|
ctx.restore();
|
|
3013
3045
|
const positionAxisGutter = Math.max(0, width - chartRight);
|
|
@@ -3432,16 +3464,18 @@ function createChart(element, options = {}) {
|
|
|
3432
3464
|
ctx.font = prevFont;
|
|
3433
3465
|
}
|
|
3434
3466
|
}
|
|
3467
|
+
const axisStepMs = getTimeStepMs();
|
|
3468
|
+
const axisIntraday = axisStepMs > 0 && axisStepMs < 24 * 60 * 60 * 1e3;
|
|
3469
|
+
let prevAxisTickTime = null;
|
|
3435
3470
|
for (let index = tickStartIndex; index <= visibleTickEnd; index += xStep) {
|
|
3436
3471
|
const tickTime = getTimeForIndex(index);
|
|
3437
3472
|
if (!tickTime) {
|
|
3438
3473
|
continue;
|
|
3439
3474
|
}
|
|
3440
3475
|
const x = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
3441
|
-
const
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
});
|
|
3476
|
+
const isNewDay = !prevAxisTickTime || prevAxisTickTime.getDate() !== tickTime.getDate() || prevAxisTickTime.getMonth() !== tickTime.getMonth() || prevAxisTickTime.getFullYear() !== tickTime.getFullYear();
|
|
3477
|
+
const timeLabel = axisIntraday && !isNewDay ? tickTime.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", hour12: false }) : tickTime.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
3478
|
+
prevAxisTickTime = tickTime;
|
|
3445
3479
|
const prevFont = ctx.font;
|
|
3446
3480
|
ctx.font = `${xAxisFontSize}px ${mergedOptions.fontFamily}`;
|
|
3447
3481
|
drawText(timeLabel, x, fullChartBottom + 8, "center", "top", xAxis.textColor);
|
package/dist/index.d.cts
CHANGED
|
@@ -241,6 +241,10 @@ interface CrosshairOptions {
|
|
|
241
241
|
priceActionButtonGap?: number;
|
|
242
242
|
priceActionButtonRounded?: boolean;
|
|
243
243
|
priceActionButtonBorderRadius?: number;
|
|
244
|
+
sideHintLeft?: string;
|
|
245
|
+
sideHintRight?: string;
|
|
246
|
+
sideHintLeftColor?: string;
|
|
247
|
+
sideHintRightColor?: string;
|
|
244
248
|
}
|
|
245
249
|
interface WatermarkOptions {
|
|
246
250
|
visible?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -241,6 +241,10 @@ interface CrosshairOptions {
|
|
|
241
241
|
priceActionButtonGap?: number;
|
|
242
242
|
priceActionButtonRounded?: boolean;
|
|
243
243
|
priceActionButtonBorderRadius?: number;
|
|
244
|
+
sideHintLeft?: string;
|
|
245
|
+
sideHintRight?: string;
|
|
246
|
+
sideHintLeftColor?: string;
|
|
247
|
+
sideHintRightColor?: string;
|
|
244
248
|
}
|
|
245
249
|
interface WatermarkOptions {
|
|
246
250
|
visible?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -49,7 +49,11 @@ var DEFAULT_CROSSHAIR_OPTIONS = {
|
|
|
49
49
|
priceActionButtonSize: 16,
|
|
50
50
|
priceActionButtonGap: 4,
|
|
51
51
|
priceActionButtonRounded: true,
|
|
52
|
-
priceActionButtonBorderRadius: 8
|
|
52
|
+
priceActionButtonBorderRadius: 8,
|
|
53
|
+
sideHintLeft: "",
|
|
54
|
+
sideHintRight: "",
|
|
55
|
+
sideHintLeftColor: "#26a69a",
|
|
56
|
+
sideHintRightColor: "#ef5350"
|
|
53
57
|
};
|
|
54
58
|
var DEFAULT_WATERMARK_OPTIONS = {
|
|
55
59
|
visible: false,
|
|
@@ -1266,10 +1270,19 @@ function createChart(element, options = {}) {
|
|
|
1266
1270
|
}
|
|
1267
1271
|
return Math.round(price / tickSize) * tickSize;
|
|
1268
1272
|
};
|
|
1273
|
+
const groupThousands = (value, decimals) => {
|
|
1274
|
+
const negative = value < 0;
|
|
1275
|
+
const fixed = Math.abs(value).toFixed(decimals);
|
|
1276
|
+
const dot = fixed.indexOf(".");
|
|
1277
|
+
const intPart = dot === -1 ? fixed : fixed.slice(0, dot);
|
|
1278
|
+
const decPart = dot === -1 ? "" : fixed.slice(dot);
|
|
1279
|
+
const grouped = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1280
|
+
return `${negative ? "-" : ""}${grouped}${decPart}`;
|
|
1281
|
+
};
|
|
1269
1282
|
const formatPrice = (price) => {
|
|
1270
1283
|
const rounded = quantizeToTickSize(price);
|
|
1271
1284
|
const decimals = getDisplayPriceDecimals();
|
|
1272
|
-
return rounded
|
|
1285
|
+
return groupThousands(rounded, decimals);
|
|
1273
1286
|
};
|
|
1274
1287
|
const roundToPricePrecision = (price) => {
|
|
1275
1288
|
const rounded = quantizeToTickSize(price);
|
|
@@ -1307,7 +1320,7 @@ function createChart(element, options = {}) {
|
|
|
1307
1320
|
}
|
|
1308
1321
|
const observedDigits = maxAbsPrice >= 1 ? Math.floor(Math.log10(maxAbsPrice)) + 1 : 1;
|
|
1309
1322
|
const integerDigits = Math.max(configuredDigits, observedDigits);
|
|
1310
|
-
const integerPart = "8".repeat(integerDigits);
|
|
1323
|
+
const integerPart = "8".repeat(integerDigits).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1311
1324
|
const decimalPart = decimals > 0 ? `.${"8".repeat(decimals)}` : "";
|
|
1312
1325
|
return `${integerPart}${decimalPart}`;
|
|
1313
1326
|
};
|
|
@@ -2982,6 +2995,25 @@ function createChart(element, options = {}) {
|
|
|
2982
2995
|
}
|
|
2983
2996
|
ctx.restore();
|
|
2984
2997
|
}
|
|
2998
|
+
if (crosshair.sideHintLeft || crosshair.sideHintRight) {
|
|
2999
|
+
ctx.save();
|
|
3000
|
+
ctx.font = `600 11px ${mergedOptions.fontFamily}`;
|
|
3001
|
+
ctx.textBaseline = "middle";
|
|
3002
|
+
ctx.setLineDash([]);
|
|
3003
|
+
const hintY = clamp(cy - 14, chartTop + 8, chartBottom - 8);
|
|
3004
|
+
const hintGap = 8;
|
|
3005
|
+
if (crosshair.sideHintLeft) {
|
|
3006
|
+
ctx.fillStyle = crosshair.sideHintLeftColor;
|
|
3007
|
+
ctx.textAlign = "right";
|
|
3008
|
+
ctx.fillText(crosshair.sideHintLeft, cx - hintGap, hintY);
|
|
3009
|
+
}
|
|
3010
|
+
if (crosshair.sideHintRight) {
|
|
3011
|
+
ctx.fillStyle = crosshair.sideHintRightColor;
|
|
3012
|
+
ctx.textAlign = "left";
|
|
3013
|
+
ctx.fillText(crosshair.sideHintRight, cx + hintGap, hintY);
|
|
3014
|
+
}
|
|
3015
|
+
ctx.restore();
|
|
3016
|
+
}
|
|
2985
3017
|
}
|
|
2986
3018
|
ctx.restore();
|
|
2987
3019
|
const positionAxisGutter = Math.max(0, width - chartRight);
|
|
@@ -3406,16 +3438,18 @@ function createChart(element, options = {}) {
|
|
|
3406
3438
|
ctx.font = prevFont;
|
|
3407
3439
|
}
|
|
3408
3440
|
}
|
|
3441
|
+
const axisStepMs = getTimeStepMs();
|
|
3442
|
+
const axisIntraday = axisStepMs > 0 && axisStepMs < 24 * 60 * 60 * 1e3;
|
|
3443
|
+
let prevAxisTickTime = null;
|
|
3409
3444
|
for (let index = tickStartIndex; index <= visibleTickEnd; index += xStep) {
|
|
3410
3445
|
const tickTime = getTimeForIndex(index);
|
|
3411
3446
|
if (!tickTime) {
|
|
3412
3447
|
continue;
|
|
3413
3448
|
}
|
|
3414
3449
|
const x = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
3415
|
-
const
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
});
|
|
3450
|
+
const isNewDay = !prevAxisTickTime || prevAxisTickTime.getDate() !== tickTime.getDate() || prevAxisTickTime.getMonth() !== tickTime.getMonth() || prevAxisTickTime.getFullYear() !== tickTime.getFullYear();
|
|
3451
|
+
const timeLabel = axisIntraday && !isNewDay ? tickTime.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", hour12: false }) : tickTime.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
3452
|
+
prevAxisTickTime = tickTime;
|
|
3419
3453
|
const prevFont = ctx.font;
|
|
3420
3454
|
ctx.font = `${xAxisFontSize}px ${mergedOptions.fontFamily}`;
|
|
3421
3455
|
drawText(timeLabel, x, fullChartBottom + 8, "center", "top", xAxis.textColor);
|