vue3+websocket 如何使外部变量获取websocket 返回的数据?

2023-06-19 374 0

<template>
  <div id="cesiumContainer"></div>
</template>
<script setup>
import { onMounted, onUnmounted, ref } from 'vue';
import * as Cesium from 'cesium';
import CesiumNavigation from 'cesium-navigation-es6'
import api from '@/api/api';
import back from '@/api/back'
import { ElMessage } from 'element-plus';
import emitter from '@/api/eventpus/eventbus';
let socketInfo = ref('ws://192.168.0.45:8089/kunchen-plsms-websocket/webSocket')
let ws = ref(new WebSocket(socketInfo.value))
let pingInterval = ref(null) // 心跳间隔ID
let viewer = ref(null)
let entity = ref(null)
// 定位终端导航实时显示
let tableData = ref([])
// 地图的基础配置
function init() {
  viewer.value = new Cesium.Viewer('cesiumContainer', {
    //cesium的查看器的基本属性
    baseLayerPicker: false,//配置图层底图的图标
    //加载谷歌影像地图,UrlTemplateImageryProvider该接口是加载谷歌地图服务的接口
    imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
      url: "https://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer",
    }),
    //需要纯色背景必须设置
    contextOptions: {
      webgl: {
        alpha: true,
      }
    },
    infoBox: false,//去除原生自带右上角弹窗
    sceneMode: 3,//初始场景模式 1 2D模式 2 2D循环模式 3 3D模式  Cesium.SceneMode
    geocoder: false,   //查找位置工具
    homeButton: true, // 视角返回初始位置
    sceneModePicker: true, //选择视角模式,有三种 3D,2D,哥伦比视图
    baseLayerPicker: false, //图层选择器,选择要显示的地图服务和地形服务
    navigationHelpButton: false, //导航帮助按钮,显示默认的地图控制帮助
    animation: false, //动画器件,控制视图动画的播放速度.
    // creditContainer: "credit", // 版权显示,显示数据归属
    timeline: false, //时间线,指示当前时间,并允许用户跳到特定的时间
    fullscreenButton: false, //全屏按钮
    vrButton: false,
    baseLayerPicker: false,
    // terrainProvider: Cesium.createWorldTerrain({ // 设置cesium世界地形
    //   requestWaterMask: true,//地形的开启
    //   requestVertexNormals: true,//水面效果的开启
    // })
  })
  // viewer.value.scene.skyBox.show = false //关闭天空盒,否则会显示天空颜色
  //背景透明
  viewer.value.scene.backgroundColor = new Cesium.Color(0.0, 0.0, 0.0, 0.0);
  //关闭大气
  viewer.value.scene.skyAtmosphere.show = false
  //抗锯齿
  viewer.value.scene.fxaa = true;
  viewer.value.scene.postProcessStages.fxaa.enabled = true;
  //清除月亮太阳
  viewer.value.scene.moon.show = false
  viewer.value.scene.sun.show = false
  // 去除logo 版权显示,显示数据归属
  viewer.value.cesiumWidget.creditContainer.style.display = "none";
  // 设置初始默认视角
  viewer.value.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(104.22809397, 30.57013838, 300000), // 成都的坐标
    orientation: {
      heading: 6.283185307179581,//方向 坐标系旋转90度
      pitch: 45,//视角 设置俯仰角度为-45度
      roll: 0.0
    }
  });
  // 修改homeButton的默认返回位置
  viewer.value.homeButton.viewModel.command.beforeExecute.addEventListener(function (e) {
    e.cancel = true;
    viewer.value.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(104.22809397, 30.57013838, 300000),
    })
  })
  // 显示帧率
  viewer.value.scene.debugShowFramesPerSecond = false;
  // 添加罗盘,比例尺等控件
  //配置项
  var options = {
    // 用于在使用重置导航重置地图视图时设置默认视图控制。接受的值是Cesium.Cartographic 和 Cesium.Rectangle.
    defaultResetView: Cesium.Rectangle.fromDegrees(80, 22, 130, 50),
    // 用于启用或禁用罗盘。true是启用罗盘,false是禁用罗盘。默认值为true。
    enableCompass: true,
    // 用于启用或禁用缩放控件。true是启用,false是禁用。默认值为true。
    enableZoomControls: true,
    // 用于启用或禁用距离图例。true是启用,false是禁用。默认值为true。
    enableDistanceLegend: true,
    // 用于启用或禁用指南针外环。true是启用,false是禁用。默认值为true。
    enableCompassOuterRing: true
  };
  // 初始化罗盘
  new CesiumNavigation(viewer.value, options);
  // --------------------------websocket--------------------------------------------
  // 初始Websocket
  ws.value.addEventListener('open', () => {
    console.log('连接已打开')
    const data = JSON.stringify({ command: 1, serializeAlgorithm: 1, token: window.localStorage.getItem('token') })
    ws.value.send(data) // 发送JSON字符串
    // 设置心跳间隔为5秒
    pingInterval.value = window.setInterval(() => {
      const pingMessage = JSON.stringify({
        command: 2,
        serializeAlgorithm: 1
      })
      ws.value.send(pingMessage)
    }, 5000)
  })
  // var list = []
  ws.value.addEventListener('message', (event) => {
    const data = JSON.parse(event.data) // 解析JSON字符串
    if (data.data == undefined) {
      console.log('未响应');
    } else {
      // list.push(data.data)
      // tableData.value = [data.data].splice(1, 1).concat(list)
      tableData.value = data.data.latitude
      emitter.emit('webDataValue', tableData.value)
      console.log('解析后的数据', tableData.value);
    }
  })
  ws.value.addEventListener('close', () => {
    window.clearInterval(pingInterval.value) // 清除心跳间隔定时器
    console.log('Websocket连接关闭');
  })
  ws.value.addEventListener('error', (error) => {
    console.log('Websocket连接错误');
    window.clearInterval(pingInterval.value) // 清除心跳间隔定时器
  })
  emitter.on('logout', () => {
    // 关闭 Websocket 连接
    ws.value.close()
    window.clearInterval(pingInterval.value) // 清除心跳间隔定时器
  })
  // 后端返回的经纬度数据
  const positions = ref([
    { longitude: 104.227155465, latitude: 30.571566765, },//中心点
    { longitude: 104.22621696, latitude: 30.57299515 }, // 左上角
    { longitude: 104.22809397, latitude: 30.57299515 }, // 右上角
    { longitude: 104.22621696, latitude: 30.57013838 }, // 左下角 
    { longitude: 104.22809397, latitude: 30.57013838 }, // 右下角
  ])
  console.log('经纬度', positions.value);
  // 添加点
  positions.value.forEach((position, index) => {
    viewer.value.entities.add({
      position: Cesium.Cartesian3.fromDegrees(position.longitude, position.latitude),
      point: {
        pixelSize: 10,
        color: Cesium.Color.RED,
        outlineColor: Cesium.Color.WHITE,
        outlineWidth: 2,
      },
      label: {
        text: `点${index + 1}`,
        font: '14pt monospace',
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth: 2,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        pixelOffset: new Cesium.Cartesian2(0, -9),
      },
    });
  });
  // 添加轨迹线
  viewer.value.entities.add({
    polyline: {
      positions: Cesium.Cartesian3.fromDegreesArray(positions.value.flatMap(pos => [pos.longitude, pos.latitude])),
      width: 2,
      material: Cesium.Color.RED,
    },
  });
  // 加载模型
  let entity = Cesium.Cartesian3.fromDegrees(104.227155465, 30.571566765,)
  let model = viewer.value.entities.add({
    id: 'model',
    position: entity,
    model: {
      // uri: 'http://127.0.0.1:5501/car/plane3_gltf.gltf',
      uri: '/car/parking_space_dae_V0.1.gltf',
      minimumPixelSize: 64,
      maximumSize: 128,
      show: true,
      color: Cesium.Color.CORAL,
      scale: 100 //放大倍数
    },
    // scale: 1.0
  });
  viewer.value.trackedEntity = model
  // viewer.value.zoomTo(Cesium.mode)
}
onMounted(() => {
  init() //加载3d地图,
})
// 在onUnmounted钩子函数中销毁Cesium Viewer
onUnmounted(() => {
  viewer.value.destroy()
})
</script>

要求是通过websocket返回的经纬度,在地图上面根据返回的经纬度绘制点和轨迹线,点和线我弄出来了(目前是用的模拟的固定经纬度),websocket返回的是实时更新的经纬度
图片.png

我不知道你的外部是什么意思。不过通常来说就几个方案:

  1. 组件间按层级传递。即子组件传递给父组件,那么 emit('change', value) 即可
  2. vue 应用内部数据传递。可以用 pinia 构建 store 来处理
  3. 全局事件总线。可以构建一个全局事件总线,用来传递信息和数据。
  4. 直接放在全局上。即 window.someVar = yourData

最简单的可以使用状态管理库。比如说 Vuex 和 Pinia。
当然如果你的项目比较小,也不想使用状态管理库,可以使用 provide/inject 来处理,但是使用 依赖注入 暴露给后代的变量默认不是响应式的,需要用一些方式来实现响应式。

如果就是一个页面完成所有处理的,就是当前页面里面初始化WS,当前页面接收信息和处理业务。可以直接在当前页面里面做,而不是在外部处理。


我当初用的 vue-native-websocket 这个库,你可以看一下文档里面有关搭配使用 Vuex 的说明。

回答

相关文章

nuxt2部署静态化和ssr的时候访问首页先报404再出现首页为什么?
`clip-path` 如何绘制圆角平行四边形呢?
多线程wait方法报错?
VUE 绑定的方法如何直接使用外部函数?
vue2固定定位该怎么做?
谁有redis实现信号量的代码,希望借鉴一下?