JS实时画走势图怎么做?
摘要:
核心概念无论使用哪种库,实现实时走势图的核心逻辑都是一样的:数据源: 你需要一个提供实时数据的地方,这可以是一个 WebSocket 连接、Server-Sent Events (... 核心概念
无论使用哪种库,实现实时走势图的核心逻辑都是一样的:
- 数据源: 你需要一个提供实时数据的地方,这可以是一个 WebSocket 连接、Server-Sent Events (SSE)、或通过定时器 (
setInterval) 模拟的 API 轮询。 - 数据存储: 你需要一个地方来存储图表的数据,通常是一个数组,它会随着新数据的到来而不断更新。
- 图表库: 你需要一个 JavaScript 库来将数据可视化,我们重点介绍最流行的几个。
- 更新机制: 当新数据到达时,你需要更新图表,这通常意味着:
- 追加数据: 将新数据点添加到数据数组的末尾。
- 移除旧数据: 为了防止数组无限增长,你需要移除最旧的数据点(只保留最新的 100 个点)。
- 重绘图表: 通知图表库使用新的数据集重新渲染。
使用 ECharts (推荐,功能强大,生态完善)
ECharts 是百度开源的一个非常强大的可视化库,它功能全面,配置灵活,非常适合复杂的图表需求。
(图片来源网络,侵删)
准备工作
在 HTML 中引入 ECharts 的库文件。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">ECharts 实时走势图</title>
<!-- 引入 ECharts 文件 -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
</head>
<body>
<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
<div id="main" style="width: 800px;height:400px;"></div>
<script src="app.js"></script>
</body>
</html>
实现代码 (app.js)
我们将模拟一个 WebSocket 数据源,并实现图表的实时更新。
// 1. 初始化图表
const chartDom = document.getElementById('main');
const myChart = echarts.init(chartDom);
let option;
// 2. 准备数据
const dataX = []; // X轴数据 (时间)
const dataY = []; // Y轴数据 (数值)
const maxDataPoints = 50; // 最多显示的数据点数量
// 3. 模拟实时数据源 (这里用 setInterval 模拟 WebSocket)
// 在实际应用中,这里会是 WebSocket.onmessage 或 SSE.onmessage
function generateData() {
const now = new Date();
const timeStr = now.toLocaleTimeString(); // 获取当前时间字符串
const value = Math.random() * 100; // 生成一个随机值
// 追加新数据
dataX.push(timeStr);
dataY.push(value);
// 移除旧数据,保持数据点数量恒定
if (dataX.length > maxDataPoints) {
dataX.shift();
dataY.shift();
}
// 更新图表配置
option = {
title: {
text: '实时数据走势图'
},
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'category',
data: dataX,
boundaryGap: false // 去除轴间距,使线条穿过
},
yAxis: {
type: 'value',
boundaryGap: [0, '10%'] // Y轴留出10%的空间
},
series: [{
name: '数据值',
type: 'line', // 折线图
data: dataY,
smooth: true, // 平滑曲线
symbol: 'none', // 去掉数据点上的小圆点
areaStyle: { // 填充区域
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(128, 255, 165, 0.3)' },
{ offset: 1, color: 'rgba(1, 191, 236, 0.1)' }
])
}
}]
};
// 4. 使用新数据更新图表
myChart.setOption(option);
}
// 初始化时先画一次
generateData();
// 设置定时器,每隔 1 秒生成一次新数据
setInterval(generateData, 1000);
// 确保在窗口大小改变时,图表也能自适应
window.addEventListener('resize', () => {
myChart.resize();
});
使用 Chart.js (轻量级,易于上手)
Chart.js 是另一个非常流行的库,以其轻量级和易用性著称。
准备工作
引入 Chart.js 库。
(图片来源网络,侵删)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">Chart.js 实时走势图</title>
<!-- 引入 Chart.js 文件 -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<canvas id="myChart" width="800" height="400"></canvas>
<script src="app-chart.js"></script>
</body>
</html>
实现代码 (app-chart.js)
// 1. 获取 canvas 上下文
const ctx = document.getElementById('myChart').getContext('2d');
// 2. 初始化图表
const myChart = new Chart(ctx, {
type: 'line', // 图表类型
data: {
labels: [], // X轴标签 (时间)
datasets: [{
label: '实时数据',
data: [], // Y轴数据 (数值)
borderColor: 'rgb(75, 192, 192)',
backgroundColor: 'rgba(75, 192, 192, 0.2)',
tension: 0.4, // 使线条平滑
fill: true // 填充线下区域
}]
},
options: {
responsive: true, // 响应式
scales: {
y: {
beginAtZero: true // Y轴从0开始
}
},
animation: {
duration: 0 // 关闭动画,使更新更流畅
}
}
});
// 3. 模拟实时数据源
const maxDataPoints = 50;
function updateChart() {
const now = new Date();
const timeStr = now.toLocaleTimeString();
const newValue = Math.random() * 100;
// 更新数据
myChart.data.labels.push(timeStr);
myChart.data.datasets[0].data.push(newValue);
// 移除旧数据
if (myChart.data.labels.length > maxDataPoints) {
myChart.data.labels.shift();
myChart.data.datasets[0].data.shift();
}
// 4. 更新图表
myChart.update('none'); // 'none' 模式可以不触发动画,性能更好
}
// 初始化时先画一次
updateChart();
// 设置定时器
setInterval(updateChart, 1000);
使用原生 Canvas (性能极致,但复杂度高)
如果你的应用对性能有极致要求,并且图表非常简单,可以考虑使用原生 Canvas API,这种方式不依赖任何第三方库,但所有逻辑都需要自己实现。
准备工作
一个 <canvas> 元素。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">原生 Canvas 实时走势图</title>
<style>
canvas { border: 1px solid #ccc; }
</style>
</head>
<body>
<canvas id="myCanvas" width="800" height="400"></canvas>
<script src="app-native.js"></script>
</body>
</html>
实现代码 (app-native.js)
这个实现稍微复杂一些,需要处理坐标转换、绘制坐标轴、绘制线条等。
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const maxDataPoints = 50;
const data = [];
// 绘制函数
function drawChart() {
// 清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 设置样式
ctx.strokeStyle = '#007bff';
ctx.lineWidth = 2;
ctx.fillStyle = 'rgba(0, 123, 255, 0.1)';
ctx.beginPath();
// 如果没有数据,则不绘制
if (data.length === 0) return;
const padding = 40; // 内边距
const chartWidth = canvas.width - 2 * padding;
const chartHeight = canvas.height - 2 * padding;
// 找出数据范围
const maxValue = Math.max(...data);
const minValue = Math.min(...data);
const valueRange = maxValue - minValue || 1; // 避免除以0
// 绘制数据点和连线
data.forEach((value, index) => {
const x = padding + (index / (maxDataPoints - 1)) * chartWidth;
// Y轴需要翻转,因为canvas的Y轴向下
const y = padding + chartHeight - ((value - minValue) / valueRange) * chartHeight;
if (index === 0) {
ctx.moveTo(x, y);
} else {
ctx.lineTo(x, y);
}
});
// 绘制线条
ctx.stroke();
// 绘制填充区域
ctx.lineTo(padding + chartWidth, padding + chartHeight);
ctx.lineTo(padding, padding + chartHeight);
ctx.closePath();
ctx.fill();
// (可选) 绘制坐标轴和标签
ctx.fillStyle = 'black';
ctx.font = '12px Arial';
ctx.fillText(`Max: ${maxValue.toFixed(2)}`, padding, padding - 10);
ctx.fillText(`Min: ${minValue.toFixed(2)}`, padding, canvas.height - padding + 20);
}
// 模拟数据源
function addData() {
const newValue = Math.random() * 100;
data.push(newValue);
if (data.length > maxDataPoints) {
data.shift();
}
drawChart();
}
// 初始化
addData();
// 定时更新
setInterval(addData, 1000);
如何连接真实数据源?
上面的例子都使用了 setInterval 来模拟数据,在实际项目中,你通常会使用 WebSocket 或 SSE。
WebSocket 示例
假设你有一个 WebSocket 服务器,它在每次有新数据时都会推送消息。
// 在 ECharts 或 Chart.js 的代码中,替换 setInterval 部分
// 1. 创建 WebSocket 连接
const socket = new WebSocket('wss://your-websocket-server.com');
// 2. 连接打开后
socket.onopen = function(event) {
console.log('WebSocket 连接已建立!');
};
// 3. 接收消息
socket.onmessage = function(event) {
// event.data 是服务器推送的数据,通常是 JSON 字符串
const newData = JSON.parse(event.data);
// 假设 newData 是 { time: '10:00:01', value: 55.5 }
const timeStr = newData.time;
const value = newData.value;
// --- 以下是更新图表的逻辑,与之前完全相同 ---
dataX.push(timeStr);
dataY.push(value);
if (dataX.length > maxDataPoints) {
dataX.shift();
dataY.shift();
}
myChart.setOption(option); // 或 myChart.update();
};
// 4. 处理错误
socket.onerror = function(error) {
console.error('WebSocket 错误:', error);
};
// 5. 连接关闭
socket.onclose = function(event) {
if (event.wasClean) {
console.log(`WebSocket 连接正常关闭,代码=${event.code} 原因=${event.reason}`);
} else {
console.error('WebSocket 连接被异常中断');
}
};
总结与选择
| 特性 | ECharts | Chart.js | 原生 Canvas |
|---|---|---|---|
| 易用性 | 中等,配置项多 | 高,非常直观 | 低,需要自己实现所有逻辑 |
| 功能丰富度 | 极高,支持各种复杂图表、3D、地图等 | 高,能满足大部分需求 | 仅限你实现的功能 |
| 性能 | 良好 | 良好 | 极高,无任何库开销 |
| 生态/文档 | 非常完善,社区活跃 | 非常完善,社区活跃 | 依赖 MDN 和自身经验 |
| 适用场景 | 专业数据可视化、复杂图表、报表 | 快速开发、中小型项目、对性能要求不极致的场景 | 游戏渲染、超高性能要求、定制化极高的场景 |
给你的建议:
- 绝大多数情况下,首选 ECharts。 它功能强大,文档齐全,能满足你几乎所有的需求,是专业开发者的首选。
- 如果你的项目很简单,或者你希望快速集成,Chart.js 是一个很好的选择。
- 只有在确认性能是瓶颈,并且你愿意投入更多开发时间时,才考虑使用 原生 Canvas。
文章版权及转载声明
作者:咔咔本文地址:https://jits.cn/content/19025.html发布于 2025-11-30
文章转载或复制请以超链接形式并注明出处杰思科技・AI 股讯


还没有评论,来说两句吧...