基于Vue+WebSocket实现实时数据可视化的实战指南

 更新时间:2025年07月31日 10:05:35   作者:saadiya~  
在现代交通大屏项目中,实时数据的采集和可视化尤为重要,本文结合 Vue3 和 ECharts,分享一个支持多 WebSocket 数据源实时合并、模拟数据调试、自动重连的完整设计方案,帮助你快速搭建健壮的数据可视化组件,需要的朋友可以参考下

一、项目背景与核心需求

  • 实时接收多个 WebSocket 数据源(不同服务器或端口)
  • 设计模拟数据接口,方便本地开发调试
  • 支持数据的自动合并(如车流总量、车辆类型分布)
  • 使用 ECharts 动态展示统计数据
  • 保证 WebSocket 断线自动重连,提高稳定性

二、项目架构与核心状态管理

定义一个全局响应式对象 sources,分别存储四个数据源的数据,支持真实数据和模拟数据统一写入。

const USE_MOCK = true; // 是否启用模拟数据 
const sources = reactive({ su1: {}, su2: {}, su3: {}, su4: {}, });

三、WebSocket 连接与模拟数据设计

1. 真实 WebSocket 连接实现

使用原生 WebSocket 连接服务器,设置事件监听,支持断线自动重连。

function createRealWS(url, setTarget) {
  const ws = new WebSocket(url);
 
  ws.onopen = () => console.log(`🟢 WebSocket ${url} 已连接`);
  
  ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    setTarget(JSON.parse(data.data));
  };
 
  ws.onerror = () => console.error(`WebSocket ${url} 出错`);
  
  ws.onclose = () => {
    console.warn(`WebSocket ${url} 关闭,3秒后重连...`);
    setTimeout(() => createRealWS(url, setTarget), 3000);
  };
}

2. 模拟数据接口

为了方便本地开发,使用定时器生成结构一致的模拟数据,模拟数据每3秒刷新一次。

function createMockSource(setTarget) {
  setInterval(() => {
    const mock = {
      timestamp: Date.now(),
      globalTime: new Date().toLocaleString(),
      totalVehiCount: Math.floor(Math.random() * 1000),
      aveSpeed: +(30 + Math.random() * 10).toFixed(2),
      numVehiByType: Object.fromEntries(
        [1, 2, 3, 7, 8, 10, 11, 15, 100].map(k => [k, Math.floor(Math.random() * 100)])
      ),
    };
    setTarget(mock);
  }, 3000);
}

3. 初始化所有数据源

根据 WebSocket URL 端口号映射到对应数据源,启用模拟或真实数据。

function initAllSources() {
  const urls = [
    "ws://xx/wsStatisJd",
    "ws://xx/wsStatisJd",
    "ws://xx/wsStatisJd",
    "ws://xx/wsStatisJd",
  ];
 
  urls.forEach((url) => {
    const key = getSourceKeyByPort(url); // su1 su2 su3 su4
    const setFn = (data) => (sources[key] = data);
 
    if (USE_MOCK) {
      createMockSource(setFn);
    } else {
      createRealWS(url, setFn);
    }
  });
}

四、数据合并与格式化

合并车流总量

将四个数据源的车辆总数相加,确保数值准确。

function mergeTotal(...totals) {
  return totals.reduce((sum, val) => sum + Number(val || 0), 0);
}

合并车辆类型分布

对每种车辆类型进行累加。

格式化合并后的车辆类型数据,固定顺序输出并计算百分比

function formatVehicleTypeData(numVehiByType, total = 0) {
  const fixedOrder = [8, 3, 2, 1, 15, 7, 10, 11, 100];
  return fixedOrder.map(key => {
    const value = numVehiByType[key] || 0;
    const name = vehicleTypeMap[key] || `类型${key}`;
    const percent = total > 0 ? ((value / total) * 100).toFixed(1) : "0.0";
    return {
      name,
      value,
      percent: Number(percent),
      color: vehicleColorMap[name] || "#999999",
    };
  });
}

五、响应式数据更新与图表刷新

通过 watchEffect 监听数据变化,自动计算合并数据并刷新 ECharts 饼图。

watchEffect(() => {
  const { su1, su2, su3, su4 } = sources;
 
  const mergedTotal = mergeTotal(
    su1.totalVehiCount,
    su2.totalVehiCount,
    su3.totalVehiCount,
    su4.totalVehiCount
  );
 
  const mergedType = mergeVehicleType(
    su1.numVehiByType || {},
    su2.numVehiByType || {},
    su3.numVehiByType || {},
    su4.numVehiByType || {}
  );
 
  chartData.value = formatVehicleTypeData(mergedType, mergedTotal);
  realtimeTime.value = new Date().toLocaleString();
  totalVehiCount.value = mergedTotal;
 
  aveSpeed.value = {
    su1: su1.aveSpeed || 0,
    su2: su2.aveSpeed || 0,
    su3: su3.aveSpeed || 0,
    su4: su4.aveSpeed || 0,
  };
 
  InitEchart2(chartData.value);
});

六、ECharts 饼图动态渲染

初始化并动态更新饼图,颜色对应车辆类型,关闭标签和提示框保证大屏美观。

const InitEchart2 = (data) => {
  const chartDom = document.getElementById("map-left-4-1-echarts");
  if (!chartDom) return;
 
  if (!myChart) {
    myChart = echarts.init(chartDom);
  }
 
  const colorList = data.map(item => item.color || "#ccc");
 
  myChart.setOption({
    color: colorList,
    tooltip: { show: false },
    series: [{
      name: "车辆类型占比",
      type: "pie",
      radius: ["55%", "80%"],
      avoidLabelOverlap: false,
      itemStyle: {
        borderRadius: 1,
        borderColor: "#2c3950",
        borderWidth: 2,
      },
      label: { show: false },
      emphasis: { scale: false, label: { show: false } },
      labelLine: { show: false },
      data: data.map(({ name, value }) => ({ name, value })),
    }],
  });
};

七、启动与定时刷新逻辑

在组件挂载时,初始化数据接口和数据源,并设置定时器周期刷新相关统计数据。

onMounted(() => {
  curDayCountData();       // 获取今日车流初始数据
  initAllSources();        // 启动 WebSocket / 模拟数据
  getDeviceOnlineData();   // 设备在线率数据
  curDayEventCountData();  // 今日事件统计
  eventHistoryCountData(); // 事件历史统计
 
  dataRefreshTimer = setInterval(() => {
    curDayCountData();
    getDeviceOnlineData();
    curDayEventCountData();
    eventHistoryCountData();
  }, 30000);
});
 
onUnmounted(() => {
  if (dataRefreshTimer) clearInterval(dataRefreshTimer);
});

八、总结

  • 多数据源实时管理,灵活切换模拟/真实数据,提升开发效率
  • 自动重连机制,保证 WebSocket 长连接稳定可靠
  • 响应式合并处理,统一计算统计数据,确保展示准确
  • ECharts 动态刷新,实现流畅视觉效果,符合大屏需求

如果你正在做交通、工业或监控领域的实时可视化,这个方案值得借鉴。

以上就是基于Vue+WebSocket实现实时数据可视化的实战指南的详细内容,更多关于Vue WebSocket实时数据可视化的资料请关注脚本之家其它相关文章!

相关文章

  • Vue中计算属性computed的示例解读

    Vue中计算属性computed的示例解读

    计算属性和普通属性一样是在模板中绑定计算属性的,当data中对应数据发生改变时,计算属性的值也会发生改变。下面这篇文章主要给大家介绍了关于Vue中计算属性computed的相关资料,需要的朋友可以参考下。
    2017-07-07
  • vue3中关于路由hash与History的设置

    vue3中关于路由hash与History的设置

    这篇文章主要介绍了vue3中关于路由hash与History的设置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • vue中get请求如何传递数组参数的方法示例

    vue中get请求如何传递数组参数的方法示例

    这篇文章主要介绍了vue中get请求如何传递数组参数的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • vue3使用threejs实现3D卡片水平旋转效果的示例代码

    vue3使用threejs实现3D卡片水平旋转效果的示例代码

    这篇文章主要介绍了在vue3中使用threejs实现3D卡片水平旋转效果,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-04-04
  • 详解为element-ui的Select和Cascader添加弹层底部操作按钮

    详解为element-ui的Select和Cascader添加弹层底部操作按钮

    这篇文章主要介绍了详解为element-ui的Select和Cascader添加弹层底部操作按钮,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • Vue通过v-for实现年份自动递增

    Vue通过v-for实现年份自动递增

    这篇文章主要为大家详细介绍了Vue通过v-for实现年份自动递增,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09
  • 基于Vue制作组织架构树组件

    基于Vue制作组织架构树组件

    最近公司在做一个基于vue开发的项目,项目需要开发一个展示组织架构的树组件,在网上搜了半天,没有找到合适的,下面小编给大家分享一个基于Vue制作组织架构树组件,需要的朋友参考下吧
    2017-12-12
  • Vue中的变量赋值问题

    Vue中的变量赋值问题

    这篇文章主要介绍了Vue中的变量赋值问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • 实例详解Vue项目使用eslint + prettier规范代码风格

    实例详解Vue项目使用eslint + prettier规范代码风格

    这篇文章主要介绍了Vue项目使用eslint + prettier规范代码风格,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2018-08-08
  • Vue编译器optimize源码分析

    Vue编译器optimize源码分析

    这篇文章主要为大家介绍了Vue 编译器optimize源码分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07

最新评论