ECharts 实时数据平滑更新实践(含 WebSocket 模拟)

在可视化项目中,常常需要实时展示动态数据,比如流量监控、设备状态、传感器数据等。

很多同学直接使用 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 仅更新 xAxisseries 数据,不重建图表实例
smooth: true 平滑曲线过渡
showSymbol: false 去掉节点圆点,避免闪烁
animationDurationUpdate 更新动画时长,控制平滑效果
shift() 限制点数上限,模拟数据流滚动

🧠 延伸思路

  • 如果使用真实 WebSocket,可在 onmessage 中替换 startMockWS 部分;

  • 也可以使用 appendData 提升大数据性能;

  • 若需要断线重连,可封装成 useRealtimeChart composable 逻辑复用。


✅ 最终效果

每秒新增一个点,曲线持续向左平滑移动,无闪烁、不卡顿、无全量重绘。

这种方式非常适合用于 实时监控类大屏、IoT、交通流量、传感器数据流等场景


如果这篇文章对你有帮助,
欢迎点赞 + 收藏 + 关注我 ❤️

后续我会继续更新更多前端实时可视化相关实践。

相关推荐
桜吹雪12 小时前
Langchain.js官方文档:构建具备按需加载技能的 SQL 助手
javascript·人工智能·node.js
han_12 小时前
一篇看懂国内外主流大模型:GPT、Claude、Gemini、DeepSeek、通义千问有什么区别?
前端·人工智能·llm
一行代码一行诗++12 小时前
注释是什么和注释该怎么写(C语言)
java·前端·javascript
涂兵兵_青石疏影12 小时前
beginPath-vs-save详解
前端
陈振wx:zchen200812 小时前
前端-面试题-JavaScript
javascript·前端面试题
泽_浪里白条12 小时前
我在 Superset 6.x 做自定义图表 + Embedded SDK 集成的实战复盘(附踩坑清单)
前端·数据可视化
幽络源小助理13 小时前
小六壬排盘工具源码 自适应双端 纯原生HTML+JS
前端·javascript·html
Championship.23.2413 小时前
Open Source Pipeline Skill深度解析:自动化开源贡献全流程
前端·javascript·html
Bigger13 小时前
🧠 前端岗位的"结构性调整":现象背后的冷思考
前端·程序员·ai编程
薯老板14 小时前
vue组件之间的通信
前端·vue.js