优化一点东西 懒得写了
This commit is contained in:
@@ -278,7 +278,7 @@ class MetricChart {
|
||||
constructor(canvas, unit = '') {
|
||||
this.canvas = canvas;
|
||||
this.ctx = canvas.getContext('2d');
|
||||
this.data = { timestamps: [], values: [] };
|
||||
this.data = { timestamps: [], values: [], series: null };
|
||||
this.unit = unit; // '%', 'B/s', etc.
|
||||
this.dpr = window.devicePixelRatio || 1;
|
||||
this.padding = { top: 10, right: 10, bottom: 20, left: 60 };
|
||||
@@ -305,7 +305,7 @@ class MetricChart {
|
||||
}
|
||||
|
||||
setData(data) {
|
||||
this.data = data || { timestamps: [], values: [] };
|
||||
this.data = data || { timestamps: [], values: [], series: null };
|
||||
this.animate();
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ class MetricChart {
|
||||
|
||||
ctx.clearRect(0, 0, w, h);
|
||||
|
||||
const { timestamps, values } = this.data;
|
||||
const { timestamps, values, series } = this.data;
|
||||
if (!timestamps || timestamps.length < 2) {
|
||||
ctx.fillStyle = '#5a6380';
|
||||
ctx.font = '11px sans-serif';
|
||||
@@ -342,15 +342,21 @@ class MetricChart {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find max with cushion
|
||||
let maxVal = Math.max(...values, 0.1);
|
||||
if (this.unit === '%' && maxVal <= 100) {
|
||||
if (maxVal > 80) maxVal = 100;
|
||||
else if (maxVal > 40) maxVal = 80;
|
||||
else if (maxVal > 20) maxVal = 50;
|
||||
else maxVal = 25;
|
||||
// Determine Y max
|
||||
let maxVal = 0;
|
||||
if (series) {
|
||||
// For stacked CPU, max sum should be 100
|
||||
maxVal = 100;
|
||||
} else {
|
||||
maxVal = maxVal * 1.25;
|
||||
maxVal = Math.max(...values, 0.1);
|
||||
if (this.unit === '%' && maxVal <= 100) {
|
||||
if (maxVal > 80) maxVal = 100;
|
||||
else if (maxVal > 40) maxVal = 80;
|
||||
else if (maxVal > 20) maxVal = 50;
|
||||
else maxVal = 25;
|
||||
} else {
|
||||
maxVal = maxVal * 1.25;
|
||||
}
|
||||
}
|
||||
|
||||
const len = timestamps.length;
|
||||
@@ -382,41 +388,102 @@ class MetricChart {
|
||||
ctx.fillText(label, p.left - 8, y + 3);
|
||||
}
|
||||
|
||||
// Path
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(getX(0), getY(values[0]));
|
||||
for (let i = 1; i < len; i++) {
|
||||
const prevX = getX(i - 1);
|
||||
const currX = getX(i);
|
||||
const prevY = getY(values[i - 1]);
|
||||
const currY = getY(values[i]);
|
||||
const midX = (prevX + currX) / 2;
|
||||
ctx.bezierCurveTo(midX, prevY, midX, currY, currX, currY);
|
||||
}
|
||||
|
||||
// Stroke
|
||||
ctx.strokeStyle = '#6366f1';
|
||||
ctx.lineWidth = 2;
|
||||
ctx.lineJoin = 'round';
|
||||
ctx.stroke();
|
||||
if (series) {
|
||||
// Draw Stacked Area
|
||||
const modes = [
|
||||
{ name: 'idle', color: 'rgba(100, 116, 139, 0.4)', stroke: '#64748b' }, // Slate
|
||||
{ name: 'other', color: 'rgba(168, 85, 247, 0.5)', stroke: '#a855f7' }, // Purple
|
||||
{ name: 'irq', color: 'rgba(234, 179, 8, 0.5)', stroke: '#eab308' }, // Yellow
|
||||
{ name: 'iowait', color: 'rgba(239, 68, 68, 0.5)', stroke: '#ef4444' }, // Red
|
||||
{ name: 'system', color: 'rgba(6, 182, 212, 0.5)', stroke: '#06b6d4' }, // Cyan
|
||||
{ name: 'user', color: 'rgba(99, 102, 241, 0.5)', stroke: '#6366f1' } // Indigo
|
||||
];
|
||||
|
||||
// Fill
|
||||
ctx.lineTo(getX(len - 1), p.top + chartH);
|
||||
ctx.lineTo(getX(0), p.top + chartH);
|
||||
ctx.closePath();
|
||||
const grad = ctx.createLinearGradient(0, p.top, 0, p.top + chartH);
|
||||
grad.addColorStop(0, 'rgba(99, 102, 241, 0.15)');
|
||||
grad.addColorStop(1, 'rgba(99, 102, 241, 0)');
|
||||
ctx.fillStyle = grad;
|
||||
ctx.fill();
|
||||
|
||||
// Last point pulse
|
||||
const lastX = getX(len - 1);
|
||||
const lastY = getY(values[len - 1]);
|
||||
ctx.beginPath();
|
||||
ctx.arc(lastX, lastY, 3, 0, Math.PI * 2);
|
||||
ctx.fillStyle = '#6366f1';
|
||||
ctx.fill();
|
||||
let currentBase = new Array(len).fill(0);
|
||||
|
||||
modes.forEach(mode => {
|
||||
const vals = series[mode.name];
|
||||
if (!vals) return;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(getX(0), getY(currentBase[0] + vals[0]));
|
||||
for (let i = 1; i < len; i++) {
|
||||
ctx.lineTo(getX(i), getY(currentBase[i] + vals[i]));
|
||||
}
|
||||
ctx.lineTo(getX(len - 1), getY(currentBase[len - 1]));
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
ctx.lineTo(getX(i), getY(currentBase[i]));
|
||||
}
|
||||
ctx.closePath();
|
||||
ctx.fillStyle = mode.color;
|
||||
ctx.fill();
|
||||
|
||||
// Stroke
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(getX(0), getY(currentBase[0] + vals[0]));
|
||||
for (let i = 1; i < len; i++) {
|
||||
ctx.lineTo(getX(i), getY(currentBase[i] + vals[i]));
|
||||
}
|
||||
ctx.strokeStyle = mode.stroke;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
|
||||
// Update base
|
||||
for (let i = 0; i < len; i++) {
|
||||
currentBase[i] += vals[i];
|
||||
}
|
||||
});
|
||||
|
||||
// Add Legend at bottom right
|
||||
ctx.font = '9px sans-serif';
|
||||
ctx.textAlign = 'right';
|
||||
let lx = w - 10;
|
||||
let ly = h - 5;
|
||||
[...modes].reverse().forEach(m => {
|
||||
ctx.fillStyle = m.stroke;
|
||||
ctx.fillRect(lx - 10, ly - 8, 8, 8);
|
||||
ctx.fillStyle = '#5a6380';
|
||||
ctx.fillText(m.name.charAt(0).toUpperCase() + m.name.slice(1), lx - 15, ly - 1);
|
||||
lx -= 60;
|
||||
});
|
||||
|
||||
} else {
|
||||
// Draw Single Line Path
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(getX(0), getY(values[0]));
|
||||
for (let i = 1; i < len; i++) {
|
||||
const prevX = getX(i - 1);
|
||||
const currX = getX(i);
|
||||
const prevY = getY(values[i - 1]);
|
||||
const currY = getY(values[i]);
|
||||
const midX = (prevX + currX) / 2;
|
||||
ctx.bezierCurveTo(midX, prevY, midX, currY, currX, currY);
|
||||
}
|
||||
|
||||
// Stroke
|
||||
ctx.strokeStyle = '#6366f1';
|
||||
ctx.lineWidth = 2;
|
||||
ctx.lineJoin = 'round';
|
||||
ctx.stroke();
|
||||
|
||||
// Fill
|
||||
ctx.lineTo(getX(len - 1), p.top + chartH);
|
||||
ctx.lineTo(getX(0), p.top + chartH);
|
||||
ctx.closePath();
|
||||
const grad = ctx.createLinearGradient(0, p.top, 0, p.top + chartH);
|
||||
grad.addColorStop(0, 'rgba(99, 102, 241, 0.15)');
|
||||
grad.addColorStop(1, 'rgba(99, 102, 241, 0)');
|
||||
ctx.fillStyle = grad;
|
||||
ctx.fill();
|
||||
|
||||
// Last point pulse
|
||||
const lastX = getX(len - 1);
|
||||
const lastY = getY(values[len - 1]);
|
||||
ctx.beginPath();
|
||||
ctx.arc(lastX, lastY, 3, 0, Math.PI * 2);
|
||||
ctx.fillStyle = '#6366f1';
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
|
||||
Reference in New Issue
Block a user