前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >websocket实现GPS数据的实时推送与地图的展示(优化)

websocket实现GPS数据的实时推送与地图的展示(优化)

作者头像
lzugis
发布2022-04-28 08:29:43
6900
发布2022-04-28 08:29:43
举报
文章被收录于专栏:跟牛老师一起学WEBGIS

概述

前两天,发布了一片文章websocket实现GPS数据的实时推送与地图的展示,文章发出后引来了不少读者的关注,也有不少读者要求做进步一优化。本文应大家的要求,对上文的内容做一个优化,优化地方包括:

  1. 加入了GPS方向的展示;
  2. 加入了GPS精度的展示;
  3. 加入了GPS轨迹的展示;

效果

img1.gif
img1.gif

实现

node模拟数据
代码语言:javascript
复制
const io = require('nodejs-websocket')
let connection = null
let gps = {}

for (let i = 0; i < 20; i++) {
  gps['gps' + i] = {
    offsetX: randomNum(-0.0001, 0.0001),
    offsetY: randomNum(-0.0001, 0.0001),
    accuracy: randomNum(50, 200)
  }
}

// 执行websocket处理连接方法
io.createServer(con => {
  console.log('new connection...')
  connection = con
  sendData()
  //处理客户端发送过来的消息
  // connection.on("text",function(data){
  //     console.log("接收到的客户端消息:" + data);
  // })
  //监听关闭
  connection.on("close", function (code, reason) {
    console.log("Connection closed")
  })
  //监听异常
  connection.on("error",() => {
    console.log('服务异常关闭...')
  })
}).listen(3000)

function sendData() {
  connection.sendText(getGpsPositions())
  setTimeout(sendData, 1000)
}

function getGpsPositions() {
  const [xmin, ymin, xmax, ymax] = [113.9875, 22.51947, 114.1066, 22.5711]
  let data = []
  for (let k in gps) {
    const d = gps[k]
    let {lon, lat} = d
    if(!d.lon) {
      d.lon = randomNum(xmin, xmax)
      d.lat = randomNum(ymin, ymax)
      d.rotate = 0
    } else {
      d.lon = d.lon + d.offsetX
      d.lat = d.lat + d.offsetY
      const angle = Math.atan2((lat - d.lat), (d.lon - lon))
      d.rotate = angle * (180/Math.PI)
    }
    data.push({
      code: k,
      coords: [d.lon, d.lat],
      accuracy: d.accuracy + randomNum(-0.5, 0.5),
      rotate: d.rotate
    })
  }
  return JSON.stringify(data)
}

function randomNum(min, max){
  return Math.random() * (max - min) + min
}
mapboxgl实现
代码语言:javascript
复制
  map.on('load', () => {
    const icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAD+SURBVFhH7ZahDsIwFEUbFB5PMJgJHEFg8GDxfAAeyT4EQ8CA5DNQkPA/4zQ8yMsCC13bIehNTpYtffe2b1s3k5SUVFZhTA5DOY2ulhy1enBmEhdYQvtxuSER2IeixB4mMiS+CDuocM0NVtCRoXFEwEACqzjCVErCC/OdCqvCdmUNXSkNIwxHEuCC7cpcLPyF2UaZu/DsSiZW9YTBUAx98OsKxVdl5oPtSi62L73biMoK+XAxBwcxeiaz96H+LaDwpIxc8H8IKa6z+nCvIUbfrj78RoTZWMyriLcVY/xp9Xa1cT9GmGcSpmnuc0zQVkJ/9kOygMZ+yZKS/l3G3AESgItFg3XtsAAAAABJRU5ErkJggg=='
    const arrow = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAnElEQVQ4T63TsQ0CMQyF4f/NgMQQ0CBR0FIx190cFIiWhhFoKdgEiRUeSoF0gO8cjkub+Evs2OLPpc9422dgBRwlNZn/BtjeApdOUJsh0QuuwKYWiYAFcAKWHaSR1EbpfAHlkO0ICdMJgV+QXmAAmUu6v9IZA8wkPVKgtg7TF7H25t4UbN+A9ahGmqqVD8AO2GdzUF45+I3ZJJb9JxbwRhEhB66xAAAAAElFTkSuQmCC'
    map.loadImage(icon, (error1, image1) => {
      if (error1) throw error1;
      map.addImage('red-arrow', image1);
      map.loadImage(arrow, (error, image) => {
        if (error) throw error;
        map.addImage('white-arrow', image);

        // 精度
        map.addSource('accuracy', {
          type: 'geojson',
          data: getGeojson([])
        });
        map.addLayer({
          id: "accuracy",
          type: "fill",
          source: "accuracy",
          paint: {
            "fill-color": 'red',
            'fill-opacity': 0.1
          }
        });

        // 轨迹
        map.addSource('route', {
          type: 'geojson',
          data: getGeojson([])
        });
        map.addLayer({
          id: "route",
          type: "line",
          source: "route",
          'layout': {
            'line-cap': 'round',
            'line-join': 'round'
          },
          'paint': {
            'line-color': '#09801a',
            'line-width': 8
          }
        });
        map.addLayer({
          'id':'route-arrow',
          'source': 'route',
          'type': 'symbol',
          'layout': {
            'symbol-placement': 'line',
            'symbol-spacing': 50,
            'icon-image': 'white-arrow',
            'icon-size': 0.5,
            'icon-allow-overlap': true
          }
        })

        // GPS 位置
        map.addSource('points', {
          type: 'geojson',
          data: getGeojson([])
        });
        map.addLayer({
          id: "circle",
          "type": "symbol",
          source: "points",
          layout: {
            'icon-image': 'red-arrow',
            'icon-size': 0.8,
            'icon-rotate': ['get', 'rotate'],
            'icon-allow-overlap': true
          }
        });


        ws = new WebSocket("ws://localhost:3000")
        ws.onopen = function() {
          console.log("当前客户端已经连接到websocket服务器")
        }

        let routeCoords = {}

        ws.onmessage = function (evt) {
          const data = JSON.parse(evt.data)
          let accuracyFeatures = []
          let routeFeatures = []
          let features = data.map(d => {
            const pt = {
              "type":"Feature",
              "properties": d,
              "geometry":{
                "type":"Point",
                "coordinates": d.coords
              }
            }
            if(!routeCoords[d.code]) routeCoords[d.code] = []
            routeCoords[d.code].push(d.coords)
            if(routeCoords[d.code].length > 1) routeFeatures.push(turf.lineString(routeCoords[d.code]))
            const circle = turf.buffer(pt, d.accuracy / 1000)
            accuracyFeatures.push(circle)
            return pt
          })
          map.getSource('accuracy').setData(getGeojson(accuracyFeatures))
          map.getSource('route').setData(getGeojson(routeFeatures))
          map.getSource('points').setData(getGeojson(features))
        };

        ws.onclose = function(){
          alert("连接已关闭...");
        };
      })
    });
  })

  function getGeojson(features) {
    return  {
      "type": "FeatureCollection",
      "features": features
    }
  }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-03-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 效果
  • 实现
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档