js 实现监控图
使用 Canvas 绘制基础监控图
Canvas 是 HTML5 提供的绘图 API,适合实现动态监控图。通过 getContext('2d') 获取绘图上下文,使用 lineTo() 和 stroke() 绘制折线。
const canvas = document.getElementById('monitorCanvas');
const ctx = canvas.getContext('2d');
function drawLineChart(data) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
data.forEach((value, index) => {
const x = index * (canvas.width / (data.length - 1));
const y = canvas.height - value * (canvas.height / 100);
index === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
});
ctx.strokeStyle = '#3498db';
ctx.stroke();
}
使用 Chart.js 快速构建
Chart.js 是流行的开源图表库,只需几行代码即可生成交互式监控图。引入库后创建 Chart 实例,配置 type: 'line' 即可。
import Chart from 'chart.js/auto';
const ctx = document.getElementById('monitorChart').getContext('2d');
const chart = new Chart(ctx, {
type: 'line',
data: {
labels: Array(24).fill().map((_, i) => `${i}:00`),
datasets: [{
label: 'CPU Usage',
data: [30, 45, 60, 55, 70, 65],
borderColor: 'rgb(75, 192, 192)'
}]
}
});
实时数据更新策略
监控图通常需要动态更新数据。使用 requestAnimationFrame 实现平滑动画,或通过 WebSocket 连接实时数据源。
// 模拟实时数据
function updateChart() {
const newData = Math.random() * 100;
chart.data.datasets[0].data.push(newData);
chart.data.datasets[0].data.shift();
chart.update();
setTimeout(updateChart, 1000);
}
updateChart();
性能优化技巧
对于高频更新的监控图,采用双缓冲技术减少闪烁。离屏 Canvas 预渲染图像,再通过 drawImage 快速切换。
const offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = canvas.width;
offscreenCanvas.height = canvas.height;
const offscreenCtx = offscreenCanvas.getContext('2d');
function render() {
// 在离屏Canvas绘制
offscreenCtx.clearRect(0, 0, canvas.width, canvas.height);
// ...绘制逻辑
// 主Canvas快速渲染
ctx.drawImage(offscreenCanvas, 0, 0);
requestAnimationFrame(render);
}
响应式设计实现
通过监听 resize 事件动态调整图表尺寸,使用 CSS 百分比确保容器自适应。
window.addEventListener('resize', () => {
chart.resize();
});
<style>
.chart-container {
width: 80vw;
height: 60vh;
}
</style>
异常数据处理
监控数据可能包含缺失值,通过线性插值填充空白点保持曲线连贯性。

function interpolateMissing(data) {
return data.map((val, i) => {
if (val !== null) return val;
const prev = data.slice(0, i).reverse().find(v => v !== null);
const next = data.slice(i).find(v => v !== null);
return prev && next ? (prev + next) / 2 : 0;
});
}






