refactor: 内联HiChart替代MiniChart/DualLineChart — 原生devicePixelRatio 2x

This commit is contained in:
qinglong
2026-06-14 14:53:34 +08:00
parent a45db99637
commit 0d79accd63
+55 -6
View File
@@ -142,6 +142,58 @@
</style> </style>
<script> <script>
// ── 内联高分辨率图表 (不依赖 chart.js) ──
function HiChart(canvasId, color, color2) {
this.canvas = document.getElementById(canvasId);
this.ctx = this.canvas.getContext('2d');
this.color = color;
this.color2 = color2 || null; // null = single line
this.data = new Array(60).fill(0);
this.data2 = color2 ? new Array(60).fill(0) : null;
this.maxVal = 100;
this._dpr = Math.min(window.devicePixelRatio || 1, 2);
this._resize();
var self = this;
window.addEventListener('resize', function(){ self._resize(); });
}
HiChart.prototype._resize = function() {
var rect = this.canvas.parentElement.getBoundingClientRect();
var w = Math.max(rect.width - 8, 100);
var h = 60;
this.canvas.width = w * this._dpr;
this.canvas.height = h * this._dpr;
this.canvas.style.width = w + 'px';
this.canvas.style.height = h + 'px';
this.ctx.setTransform(this._dpr, 0, 0, this._dpr, 0, 0);
this._draw();
};
HiChart.prototype.update = function(val, val2) {
this.data.push(val);
if (this.data.length > 60) this.data.shift();
if (this.data2) { this.data2.push(val2||0); if (this.data2.length > 60) this.data2.shift(); }
var all = this.data2 ? this.data.concat(this.data2) : this.data;
this.maxVal = Math.max.apply(null, all.concat([100]));
this._draw();
};
HiChart.prototype._draw = function() {
var ctx = this.ctx, w = this.canvas.width / this._dpr, h = this.canvas.height / this._dpr;
ctx.clearRect(0, 0, w, h);
var drawLine = function(data, color, dash) {
ctx.strokeStyle = color; ctx.lineWidth = 2; ctx.beginPath();
if (dash) ctx.setLineDash([4, 3]); else ctx.setLineDash([]);
var step = w / (data.length - 1);
var scale = (h - 4) / Math.max(this.maxVal, 1);
for (var i = 0; i < data.length; i++) {
var x = i * step, y = h - 4 - data[i] * scale;
if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);
}
ctx.stroke();
}.bind(this);
drawLine(this.data, this.color, false);
if (this.data2) drawLine(this.data2, this.color2, true);
};
// 确保 chart.js 已加载 (SPA 导航时可能未加载) // 确保 chart.js 已加载 (SPA 导航时可能未加载)
var pollTimer = null; var pollTimer = null;
@@ -154,7 +206,7 @@
var btn = document.getElementById("btn-layout"); var btn = document.getElementById("btn-layout");
var grid = document.getElementById("sentinel-grid"); var grid = document.getElementById("sentinel-grid");
// 销毁旧图表 // 销毁旧图表
try { Object.keys(_chartInstances).forEach(function(k){ var chs = _chartInstances[k]; if(chs) { Object.values(chs).forEach(function(c){ if(c&&c.destroy)c.destroy(); }); } }); } catch(e) {} try { Object.keys(_chartInstances).forEach(function(k){ _chartInstances[k] = null; }); } catch(e) {}
_chartInstances = {}; _chartInstances = {};
_cardCache = {}; _cardCache = {};
_firstRender = true; _firstRender = true;
@@ -206,7 +258,7 @@
var grid = document.getElementById("sentinel-grid"); var grid = document.getElementById("sentinel-grid");
if (!nodes.length) { if (!nodes.length) {
grid.innerHTML = '<div class="card" style="text-align:center;padding:24px;color:var(--text-dim)">暂无节点 — 切换到节点管理添加</div>'; grid.innerHTML = '<div class="card" style="text-align:center;padding:24px;color:var(--text-dim)">暂无节点 — 切换到节点管理添加</div>';
try { Object.keys(_chartInstances).forEach(function(k){ var chs = _chartInstances[k]; if(chs) { Object.values(chs).forEach(function(c){ if(c&&c.destroy)c.destroy(); }); } }); } catch(e) {} try { Object.keys(_chartInstances).forEach(function(k){ _chartInstances[k] = null; }); } catch(e) {}
_chartInstances = {}; _chartInstances = {};
_cardCache = {}; _cardCache = {};
_firstRender = true; _firstRender = true;
@@ -321,10 +373,7 @@
try { try {
if (charts.cpu) charts.cpu.update(cpuVal); if (charts.cpu) charts.cpu.update(cpuVal);
if (charts.mem) charts.mem.update(memVal); if (charts.mem) charts.mem.update(memVal);
if (charts.net) { if (charts.net) { charts.net.update(net.rx_bytes_sec||0, net.tx_bytes_sec||0); if (charts.net.maxVal < 102400) charts.net.maxVal = 102400; }
charts.net.update(net.rx_bytes_sec||0, net.tx_bytes_sec||0);
if (charts.net.maxVal < 102400) { charts.net.maxVal = 102400; charts.net.draw(); }
}
} catch(e) {} } catch(e) {}
} }
// 更新额外指标 // 更新额外指标