优化Again
This commit is contained in:
@@ -74,6 +74,7 @@ class AreaChart {
|
||||
const ctx = this.ctx;
|
||||
const w = this.width;
|
||||
const h = this.height;
|
||||
this.padding = { top: 20, right: 16, bottom: 32, left: 64 };
|
||||
const p = this.padding;
|
||||
const chartW = w - p.left - p.right;
|
||||
const chartH = h - p.top - p.bottom;
|
||||
@@ -89,22 +90,48 @@ class AreaChart {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find max
|
||||
let maxVal = 0;
|
||||
// Find max raw value
|
||||
let maxDataVal = 0;
|
||||
for (let i = 0; i < rx.length; i++) {
|
||||
maxVal = Math.max(maxVal, rx[i] || 0, tx[i] || 0);
|
||||
maxDataVal = Math.max(maxDataVal, rx[i] || 0, tx[i] || 0);
|
||||
}
|
||||
maxVal = maxVal * 1.15 || 1;
|
||||
|
||||
// Determine consistent unit based on max data value
|
||||
const k = 1024;
|
||||
const sizes = ['B/s', 'KB/s', 'MB/s', 'GB/s', 'TB/s'];
|
||||
let unitIdx = Math.floor(Math.log(Math.max(1, maxDataVal)) / Math.log(k));
|
||||
unitIdx = Math.max(0, Math.min(unitIdx, sizes.length - 1));
|
||||
const unitFactor = Math.pow(k, unitIdx);
|
||||
const unitLabel = sizes[unitIdx];
|
||||
|
||||
// Get value in current units and find a "nice" round max
|
||||
// Use 1.15 cushion
|
||||
const rawValInUnit = (maxDataVal * 1.15) / unitFactor;
|
||||
let niceMaxInUnit;
|
||||
|
||||
if (rawValInUnit <= 1) niceMaxInUnit = 1;
|
||||
else if (rawValInUnit <= 2) niceMaxInUnit = 2;
|
||||
else if (rawValInUnit <= 5) niceMaxInUnit = 5;
|
||||
else if (rawValInUnit <= 10) niceMaxInUnit = 10;
|
||||
else if (rawValInUnit <= 20) niceMaxInUnit = 20;
|
||||
else if (rawValInUnit <= 50) niceMaxInUnit = 50;
|
||||
else if (rawValInUnit <= 100) niceMaxInUnit = 100;
|
||||
else if (rawValInUnit <= 200) niceMaxInUnit = 200;
|
||||
else if (rawValInUnit <= 500) niceMaxInUnit = 500;
|
||||
else if (rawValInUnit <= 1000) niceMaxInUnit = 1000;
|
||||
else niceMaxInUnit = Math.ceil(rawValInUnit / 100) * 100;
|
||||
|
||||
const maxVal = niceMaxInUnit * unitFactor;
|
||||
|
||||
const len = timestamps.length;
|
||||
const xStep = chartW / (len - 1);
|
||||
|
||||
// Helper to get point
|
||||
const getX = (i) => p.left + i * xStep;
|
||||
const getY = (val) => p.top + chartH - (val / maxVal) * chartH * this.animProgress;
|
||||
const getY = (val) => p.top + chartH - (val / (maxVal || 1)) * chartH * this.animProgress;
|
||||
|
||||
// Draw grid lines
|
||||
ctx.strokeStyle = 'rgba(99, 102, 241, 0.06)';
|
||||
ctx.strokeStyle = 'rgba(99, 102, 241, 0.08)';
|
||||
ctx.lineWidth = 1;
|
||||
const gridLines = 4;
|
||||
for (let i = 0; i <= gridLines; i++) {
|
||||
@@ -114,12 +141,15 @@ class AreaChart {
|
||||
ctx.lineTo(p.left + chartW, y);
|
||||
ctx.stroke();
|
||||
|
||||
// Y-axis labels
|
||||
const val = maxVal * (1 - i / gridLines);
|
||||
// Y-axis labels - share the same unit for readability
|
||||
const valInUnit = niceMaxInUnit * (1 - i / gridLines);
|
||||
ctx.fillStyle = '#5a6380';
|
||||
ctx.font = '10px "JetBrains Mono", monospace';
|
||||
ctx.textAlign = 'right';
|
||||
ctx.fillText(formatBandwidth(val, 1), p.left - 8, y + 3);
|
||||
|
||||
// Format: "X.X MB/s" or "X MB/s"
|
||||
const label = (valInUnit % 1 === 0 ? valInUnit : valInUnit.toFixed(1)) + ' ' + unitLabel;
|
||||
ctx.fillText(label, p.left - 10, y + 3);
|
||||
}
|
||||
|
||||
// X-axis labels (every ~4 hours)
|
||||
|
||||
@@ -9,7 +9,8 @@ function formatBytes(bytes, decimals = 2) {
|
||||
if (!bytes || bytes === 0) return '0 B';
|
||||
const k = 1024;
|
||||
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
||||
const i = Math.floor(Math.log(Math.abs(bytes)) / Math.log(k));
|
||||
let i = Math.floor(Math.log(Math.abs(bytes)) / Math.log(k));
|
||||
i = Math.max(0, Math.min(i, sizes.length - 1));
|
||||
const value = bytes / Math.pow(k, i);
|
||||
return value.toFixed(decimals) + ' ' + sizes[i];
|
||||
}
|
||||
@@ -21,7 +22,8 @@ function formatBandwidth(bytesPerSec, decimals = 2) {
|
||||
if (!bytesPerSec || bytesPerSec === 0) return '0 B/s';
|
||||
const k = 1024;
|
||||
const sizes = ['B/s', 'KB/s', 'MB/s', 'GB/s', 'TB/s'];
|
||||
const i = Math.floor(Math.log(Math.abs(bytesPerSec)) / Math.log(k));
|
||||
let i = Math.floor(Math.log(Math.abs(bytesPerSec)) / Math.log(k));
|
||||
i = Math.max(0, Math.min(i, sizes.length - 1));
|
||||
const value = bytesPerSec / Math.pow(k, i);
|
||||
return value.toFixed(decimals) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user