在可视化项目中,常常需要实时展示动态数据,比如流量监控、设备状态、传感器数据等。
很多同学直接使用 setOption 全量更新数据,会导致 图表闪烁、重绘、动画不连贯。
本文介绍一种更平滑的更新方案:通过监听数据流变化,实现折线图平移更新 。
示例中我们使用 模拟 WebSocket 推送 的方式,每秒更新一次数据,图表平滑移动。
🎬 实现效果
折线图每秒新增一个点,曲线平滑向左移动,旧数据自动移除。

<template>
<div class="chart-container">
<div ref="chartRef" class="chart"></div>
</div>
</template>
<script setup>
import * as echarts from "echarts";
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
const chartRef = ref(null);
let chartInstance = null;
// 模拟 WebSocket 推送的数据数组
const chartData = ref([]);
const maxPoints = 30; // 显示的点数上限
let timer = null;
// ===================== 初始化 ECharts =====================
const initChart = () => {
chartInstance = echarts.init(chartRef.value);
const option = {
title: {
text: "实时数据曲线(平滑移动)",
left: "center",
textStyle: { fontSize: 14 },
},
tooltip: { trigger: "axis" },
grid: { top: 40, left: 40, right: 20, bottom: 40 },
xAxis: {
type: "category",
boundaryGap: false,
data: [],
},
yAxis: {
type: "value",
min: 0,
max: 100,
splitLine: { lineStyle: { color: "#eee" } },
},
series: [
{
name: "数据流",
type: "line",
smooth: true,
showSymbol: false,
data: [],
lineStyle: { color: "#4fc3f7" },
areaStyle: { color: "rgba(79,195,247,0.2)" },
},
],
animationDurationUpdate: 300,
};
chartInstance.setOption(option);
};
// ===================== 模拟 WebSocket 推送 =====================
const startMockWS = () => {
timer = setInterval(() => {
const now = new Date().toLocaleTimeString().split(" ")[0];
const value = +(Math.random() * 100).toFixed(2);
chartData.value.push({ time: now, value });
if (chartData.value.length > maxPoints) chartData.value.shift();
}, 1000);
};
// ===================== 数据监听(核心逻辑) =====================
watch(
chartData,
(val) => {
if (!chartInstance) return;
const xData = val.map((item) => item.time);
const yData = val.map((item) => item.value);
// ✅ 平滑更新:不重绘,只更新数据
chartInstance.setOption({
xAxis: { data: xData },
series: [{ data: yData }],
});
},
{ deep: true }
);
// ===================== 生命周期 =====================
onMounted(() => {
initChart();
startMockWS();
});
onBeforeUnmount(() => {
clearInterval(timer);
chartInstance?.dispose();
});
</script>
<style scoped>
.chart-container {
width: 100%;
height: 400px;
}
.chart {
width: 100%;
height: 100%;
}
</style>
🔍 技术要点总结
| 技术点 | 说明 |
|---|---|
watch(chartData) |
深度监听数据变化,即使数值没变也触发更新 |
setOption |
仅更新 xAxis 和 series 数据,不重建图表实例 |
smooth: true |
平滑曲线过渡 |
showSymbol: false |
去掉节点圆点,避免闪烁 |
animationDurationUpdate |
更新动画时长,控制平滑效果 |
shift() |
限制点数上限,模拟数据流滚动 |
🧠 延伸思路
-
如果使用真实 WebSocket,可在
onmessage中替换startMockWS部分; -
也可以使用
appendData提升大数据性能; -
若需要断线重连,可封装成
useRealtimeChartcomposable 逻辑复用。
✅ 最终效果
每秒新增一个点,曲线持续向左平滑移动,无闪烁、不卡顿、无全量重绘。
这种方式非常适合用于 实时监控类大屏、IoT、交通流量、传感器数据流等场景。
如果这篇文章对你有帮助,
欢迎点赞 + 收藏 + 关注我 ❤️
后续我会继续更新更多前端实时可视化相关实践。