vue中使用百度地图 添加标记物,点击标记物弹窗,画运动轨迹,位置纠偏,逆地址解析

2023-10-27

在vue项目中使用百度地图,添加标记物、位置纠偏、信息弹窗、画轨迹,坐标转换,逆地址解析

参考vue-baidu-map开发文档

  1. 安装 npm install vue-baidu-map --save
  2. 全局注册,在main.js中引入以下代码
    import BaiduMap from ‘vue-baidu-map’
    Vue.use(BaiduMap, {
    ak: ‘申请的百度地图ak’
    })
  3. 页面引用
<div id="allmap">
  <baidu-map class="bm-view"
             :center="center"
             @ready="handler">
  </baidu-map>
</div>
<style scoped lang="scss">
#allmap {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: absolute;
}
</style>
// 引入自定义图标
import icon from '@/assets/image/icon.png'

调用接口获取经纬度数据,初始化地图并添加marker,其中涉及到this指代逆地址解析坐标转换(百度地图位置纠偏) 等。

  1. 调用接口获取经纬度集合,经纬度坐标为百度坐标的不用转换,为GPS坐标等其它坐标类型时需要转换为百度坐标;
  2. 获取到经纬度集合数据后,进行地图初始化,设置地图中心位置、缩放比例、是否可鼠标滚动缩放,添加标记点等;
  3. 标记点上添加点击事件并弹窗信息。
getData() {
  this.locationData = []  //初始化经纬度数组集
  let self = this
  let query = {
    ...... // 接口请求参数
  }
  // 调用接口获取经纬度数组集
  dataList(query).then(res => {
    this.listData = res.data.list
    this.listData.map(row => {
      if (row.longitude && row.longitude) {
        let real_point = new BMap.Point(row.longitude, row.latitude);
        // 将gps经纬度转换成百度地图的经纬度
        new BMap.Convertor().translate([real_point], 1, 5, function (data) {
          if (data.status === 0) {
            self.locationData.push(data.points[0]);
          }
        })
      }
    })
    // 设置延迟,待数据获取到后初始化地图,handler方法在下面定义
    this.$nextTick(() => {
      setTimeout(() => {
        self.handler(self.locationData)
      }, 400);
    });
  }).catch(error => {
    console.log(error)
  })
},

// 地图初始化
handler(locationData) {
  let self = this
  var map = new BMap.Map("allmap", {
    enableMapClick: false
  });
  // 设置中心位置点
  let point = new BMap.Point(116.404, 39.915);
  map.centerAndZoom(point, 12);
  // 地图比例尺
  map.addControl(new BMap.ScaleControl({
    anchor: BMAP_ANCHOR_BOTTOM_RIGHT
  }));
  // 鼠标滑动缩放
  map.enableScrollWheelZoom(true);
  this.$nextTick(() => {
    setTimeout(() => {
       map.setViewport(locationData);
       // 调用添加标记物方法
       self.addMarker(locationData, map);
    }, 100);
  });
},

// 向地图添加经纬度位置点标记物
addMarker(pointArray, map) {
  let self = this
  let marker;
  for (var i = 0; i < pointArray.length; i++) {
    // 自定义图标
    let icon = new BMap.Icon(icon, new BMap.Size(26, 45), {
      imageOffset: new BMap.Size(-25 - 17, 0),
      anchor: new BMap.Size(13, 40)
    });
    marker = new BMap.Marker(pointArray[i], {
      icon: icon
    });
    map.addOverlay(marker);
    // 设置标记物上的文字
    marker.setLabel(new BMap.Label('标记点说明'));
    // 调用点击标记物显示信息弹窗
    this.setInfo(map, marker, pointArray[i])
  }
},

// 设置点击地图标记点信息弹窗的内容 self指代window,避免与地图fuc的this混淆
setInfo(map, marker, pt) {
  let self = this
  var opts = {
    width: 170, // 信息窗口宽度
    height: 170, // 信息窗口高度
    title: "位置信息", // 信息窗口标题
  }
  marker.addEventListener("click", function (e) {
    // 逆地址解析-根据经纬度获取中文地址
    self.getAddress(pt)
    // 设置延迟,等获取到中文地址再显示弹窗信息
    self.$nextTick(() => {
      setTimeout(() => {
        str = "经度:" + pt.lng + "<br>纬度:" + pt.lat + "<br>地址:" + self.address
        let infoWindow = new BMap.InfoWindow(str, opts); // 创建信息窗口对象 
        map.openInfoWindow(infoWindow, pt); //开启信息窗口
      }, 200);
    });
  });
},
 // 逆地址解析-根据经纬度获取中文地址
getAddress(point) {
  let self = this
  let geoc = new BMap.Geocoder({
    extensions_town: true
  });
  // 根据坐标得到地址描述    
  geoc.getLocation(new BMap.Point(point.lng, point.lat), function (result) {
    if (result) {
      self.address = result.address
    }
  });
}

定时调用接口画实时运动轨迹,如果是历史轨迹就稍微简单点。同时注意跟添加标记物一样,要注意经纬度坐标是不是百度地图坐标,不是则需要进行转换,我的经纬度坐标是GPS坐标,转换的地方有注释。

  1. 起点位置,调用一次接口获取起点并进行标记;
  2. 设置定时器调用接口获取下一个经纬度坐标,定时器设置时长根据后端实时获取到的数据进行设置,要比后端时间稍长,同时要处理后端没有获取到经纬度或者无效经纬度的情况(比如用前一个点代替);
  3. 有2个经纬度坐标就可以进行划线;
  4. 设置当前位置的marker,为矢量小车图标,同时根据当前划线的角度纠正小车图标头部朝向前进方向,不需要区分方向的图标则不用进行角度处理;
  5. 页面关闭或者长时间不操作页面时注意定时器的清除。
handleMap(row) {
  this.infoData = row
  clearInterval(this.timer);
  let self = this
  self.lineArray = []
  var map = new BMap.Map("allmap", {
    enableMapClick: false
  });
  // 先调用一次获取到初始的起点,再启动定时器,避免初始化时没有图标
  getData(row.id).then(res => {
    if (res.status === 200) {
      if (res.data != '' && res.data.longitude && res.data.latitude) {
        longLatitude(res.data.gps)
        self.center = {
          lng: res.data.longitude,
          lat: res.data.latitude
        }
        let point = new BMap.Point(self.center.lng, self.center.lat);
        map.centerAndZoom(point, 14);
        // 画轨迹
        self.addLine(map)
        self.timer = setInterval(() => {
          self.getData(row.id)
        }, 2000)
      } else {
        self.center = {
          lng: row.longitude,
          lat: row.latitude,
        }
        let real_point = new BMap.Point(self.center.lng, self.center.lat);
        new BMap.Convertor().translate([real_point], 1, 5, function (data) {
          if (data.status === 0) {
            point.push(data.points[0])
            map.centerAndZoom(data.points[0], 12);
            self.setCarIcon(map, row, data.points[0]);
          }
        })
      }
    }
  }).catch(error => {
    console.log(error)
  })
  map.enableScrollWheelZoom(true);
  map.addControl(new BMap.ScaleControl({
    anchor: BMAP_ANCHOR_BOTTOM_RIGHT
  }));
},

// 获取经纬度数据
getData(id) {
  let self = this
  vehicleStatus(id).then(res => {
    if (res.status === 200) {
      self.center = {
        lng: res.data.longitude,
        lat: res.data.latitude
      }
      let real_point = new BMap.Point(self.center.lng, self.center.lat);
      new BMap.Convertor().translate([real_point], 1, 5, function (data) {
        if (data.status === 0) {
          self.lineArray.push(data.points[0]);
        }
      })
    }
  }).catch(error => {
    console.log(error)
  })
}
// 划线
addLine(map) {
  let self = this
  var PointArr = []
  let real_point = new BMap.Point(self.center.lng, self.center.lat);
  new BMap.Convertor().translate([real_point], 1, 5, function (data) {
    if (data.status === 0) {
      self.lineArray.push(data.points[0]);
      addStartMarker(new BMap.Point(data.points[0].lng, data.points[0].lat), '起点', map);
    }
  })
  PointArr = self.lineArray
  // 自定义运动中的显示图片
  var drivingPoint = new BMap.Icon('../../assets/image/icon.png', new BMap.Size(48, 24), {
    anchor: new BMap.Size(24, 12),
    imageSize: new BMap.Size(48, 24)
  });
  var i = 0;
  var interval = setInterval(function () {
    if (i >= PointArr.length && PointArr.length > 1) {
      clearInterval(interval);
      return;
    }
    if (PointArr.length > 60) {
      clearInterval(interval);
      return;
    }
    drowLine(map, PointArr[i], PointArr[i + 1]);
    map.setCenter(PointArr[i + 1]);
    i = i + 1;
  }, 4000);

  // 划线
  function drowLine(map, PointArr, PointArrNext) {
    if (PointArr != undefined && PointArrNext != undefined) {
      var polyline = new BMap.Polyline(
        [
          new BMap.Point(PointArr.lng, PointArr.lat),
          new BMap.Point(PointArrNext.lng, PointArrNext.lat)
        ], {
          strokeColor: "blue",
          strokeWeight: 4,
          strokeOpacity: 0.8
        });
      map.addOverlay(polyline);
      addMarkerEnd(new BMap.Point(PointArrNext.lng, PointArrNext.lat), '行驶图标', map, new BMap.Point(PointArr.lng, PointArr.lat)); // 添加图标
    } else {
      addMarkerEnd(new BMap.Point(PointArr.lng, PointArr.lat), '终点', map, new BMap.Point(PointArr.lng, PointArr.lat)); // 添加终点图标
    }
  }

  // 设置起始图标
  addStartMarker(point, name, mapInit) {
      if (name == "起点") {
        window.marker = new BMap.Marker(point, {
          icon: drivingPoint
        }); // 创建标注
        mapInit.addOverlay(window.marker); // 将标注添加到地图中
      }
    },
    // 设置行驶和终点图标
    let carMk;
  function addMarkerEnd(point, name, mapInit, prePoint) {
    if (name == "行驶图标") {
      if (carMk) {
        mapInit.removeOverlay(carMk);
      }
      carMk = new BMap.Marker(point, {
        icon: drivingPoint
      });
      carMk.setRotation(getAngle(point, prePoint) - 90); // 旋转的角度
      mapInit.removeOverlay(window.marker) // 将起点图标移除
      mapInit.addOverlay(carMk);
    } else {
      mapInit.removeOverlay(carMk);
      carMk = new BMap.Marker(point, {
        icon: drivingPoint
      });
      carMk.setRotation(getAngle(point, prePoint) - 90);
      mapInit.addOverlay(carMk);
    }
  }
  //获得角度的函数
  function getAngle(n, next) {
    var ret
    var w1 = n.lat / 180 * Math.PI
    var j1 = n.lng / 180 * Math.PI
    var w2 = next.lat / 180 * Math.PI
    var j2 = next.lng / 180 * Math.PI
    ret = 4 * Math.pow(Math.sin((w1 - w2) / 2), 2) - Math.pow(Math.sin((j1 - j2) / 2) * (Math.cos(w1) - Math.cos(w2)), 2);
    ret = Math.sqrt(ret);
    var temp = Math.sin((j1 - j2) / 2) * (Math.cos(w1) + Math.cos(w2));
    ret = ret / temp;
    ret = (Math.atan(ret) / Math.PI * 180) + 180;
    ret += 90;
    if (j1 - j2 < 0) {
      if (w1 - w2 < 0) {
        ret;
      } else {
        ret = -ret + 180;
      }
    } else {
      if (w1 - w2 < 0) {
        ret = 180 + ret;
      } else {
        ret = -ret;
      }
    }
    // 某个点没有经纬度时取上一次的角度
    if (!isNaN(ret)) {
      localStorage.setItem('retobj', JSON.stringify(ret))
    } else {
      ret = JSON.parse(localStorage.getItem('retobj'));
    }
    return ret;
  }
}

tips:坐标转换也可以用coordtransform,使用方法见
https://github.com/wandergis/coordtransform,使用这个方法时最好使用new BMap.Point(point) 处理下,不然有些地方像setCenter(point),逆地址解析时会不起作用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue中使用百度地图 添加标记物,点击标记物弹窗,画运动轨迹,位置纠偏,逆地址解析 的相关文章

  • chatgpt赋能python:Python数据框基本操作

    Python 数据框基本操作 Python 是一种流行的编程语言 常用于数据分析 数据科学和机器学习等领域 Python 中数据框是一种非常重要的数据类型 也被称为表格或二维数组 本文将介绍 Python 数据框的基本操作 什么是 Pyth
  • jenkins 公钥配置

    Jenkins所在服务器linuxA 应用服务器LinuxB a生成的公钥 放到B服务器 服务器B 在 root ssh路径下建立authorized keys文件 将服务器A生成的id rsa pub 公钥 内容复制到authorized

随机推荐

  • 前端对json配置文件的读取

    一 JSON文件的数据格式为 名字为 path json ipPath http 10 12 37 11 8085 二 在前端页面中对文件进行读取 其中返回的data的数据类型是object 对path json文件进行读取 getJSON
  • 07 Linux补充|秋招刷题|9月6日

    目录 Linux 结构体内存字节对齐 静态变量static 空指针 Linux 结构体内存字节对齐 结构体内存字节要对 32位系统 4 8 32 64位系统 8 16 24 字节对 字节对 是指在计算机中 各种类型数据按照 定的规则在空间上
  • 解决Win10家庭版没有‘本地用户和组’问题

    win10系统是家庭版 并且没有本地用户和组 处理方法 将系统升至为win10专业版 然后下载microKMS v17 02 14做的激活 1 打开运行窗口 输入 gpedit msc或者secpol msc 点击确定 弹出提示框提示找不到
  • 视频flv转mp4最快的几种方法(就是不用格式工厂)

    FFmpeg 是一个非常优秀的视频处理开源工具 假如你想把avi或者flv转成mpp4的时候 你就不必要用格式工厂很繁琐的方式去转换格式 因为比如flv和mp4他的编码 视频编码和音频编码 都是h 264编码其实并没有变 这是封装格式不一样
  • 算法学习day27

    文章目录 39 组合总和 回溯法 40 组合总和II 回溯 131 分割回文串 回溯 39 组合总和 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target 找出 candidates 中可以使数字和为目标数
  • mybatis中resultMap和resultType区别,三分钟读懂

    先说结论 resultmap与resulttype的区别为 对象不同 描述不同 类型适用不同 说人话就是 resultmap和resulttype功能差不多 但是resultmap功能更强大 resultType 使用resultType进
  • 成员变量与属性是不同的

    成员变量 在类体的变量部分中定义的变量 也称为字段 属性 官方定义为属性是指get或者set方法名 去掉get或者set后 把剩余的部分首字母改为小写后 即为这个类的属性 例 public class Test private String
  • 基础算法01

    冒泡排序 基本思想是 将相邻的记录的关键码进行比较 若前面记录的关键码大于后面记录的关键码 则将它们交换 否则不交换 bool swapped true do swapped false for int i 0 i
  • 在idea中配置 gitignore忽略文件(一)

    针对一些不用每次提交的文件 设置不让其提交到git的本地仓库中 先在idea中安装gitignore插件 点击File gt Settings 选择plugs 在右边搜索 ignore 点击Install 安装完成后就可以愉快的使用了 不过
  • 界面、线程与Qt线程

    1 当界面的操作频率很高 而且还要考虑用户体验时 耗时的操作会独占系统cpu资源 让界面卡死在那里 这时需要考虑多线程方案 将耗时的操作放在 线程中执行 如下例 界面需要不停地添加字符串 如果不使用线程处理的话界面会卡死 下面我们先使用UC
  • 主成分分析(Principal Component Analysis,PCA)详解

    PCA是非常重要的统计方法 其实际应用非常广泛 但是很多讲解太过于公式化 很难让初学者消化 本文将从一个实际例子出发 并对数学公式原理及推导过程作出详细解释 即使你的数学基础比较差 在看完这篇博客之后 相信你会对PCA会有一个透彻的认知 P
  • 构造函数初始化:提高代码可读性和执行效率

    在C 中 构造函数是用来初始化对象数据成员的 一个对象在创建的时候 构造函数会被自动调用 以便为该对象的数据成员赋初值 传统的初始化方式是在构造函数内部对数据成员逐一进行初始化 这种方式虽然可行 但是代码复杂度高且效率低下 本文将介绍如何使
  • 一文详解!嵌入式软件的自动化测试框架、测试流程与功能研究分析

    目录 引言 1 嵌入式软件自动化测试平台分析 2 嵌入式软件自动化测试平台概要设计 3 嵌入式软件自动化测试平台详细设计 3 3 功能设计 引言 嵌入式软件是指被设计用于嵌入或控制另一个产品 设备或系统的软件 它在各种应用领域 例如消费电子
  • 如何批量提取不同文件夹下的图片并随机重命名

    问题提出 无论是在为了跑深度学习模型而准备数据集 还是其他的一些用途 相信大家都会遇到一个问题 我所需要的图片分布在很多不同的文件夹下 但我不需要这么多文件夹 那么我如果要使用这些图片的话 就需要把这些文件夹下的图片一个个提取出来 然后再放
  • GEE-页面介绍

    页面介绍 一 首页介绍 二 Datasets 1 Home首页介绍 1 1Climate and Weather 对应上面的 Browse by tags 标签 即为按照标签访问数据 1 2Imagery 对应上面的 landsat MOD
  • 蓝桥杯JAVA B组 2020(2)第三题 合并检测

    一 题目描述 如果结果为阴性 则说明这 k个人都是阴性 用一个试剂盒完成了 k 个人的检测 如果结果为阳性 则说明至少有一个人为阳性 需要将这 k 个人的样本全部重新独立检测 加上最开始的合并检测 一共使用了 k 1 个试剂盒完成了 k 个
  • 基于ssm框架的毕业设计管理系统 毕业设计-附源码211633

    摘 要 随着科学技术的飞速发展 各行各业都在努力与现代先进技术接轨 通过科技手段提高自身的优势 对于毕业设计管理系统当然也不能排除在外 随着网络技术的不断成熟 带动了毕业设计管理系统 它彻底改变了过去传统的管理方式 不仅使服务管理难度变低了
  • VMware出现“该虚拟机似乎正在使用中”问题

    按照以下步骤解决虚拟机异常关机无法打开问题 1 在用VMware虚拟机的时候 有时会发现打开虚拟机时提示 该虚拟机似乎正在使用中 如果该虚拟机未在使用 请按 获取所有权 T 按钮获取它的所有权 否则 请按 取消 按钮以防损坏 配置文件 D
  • Android——使用DatePicker和TimePicker显示当前日期和时间

    1 DatePicker和TimePicker两种实现动态输入日期和时间的功能 2 DatePickerDialog和TimePickerDialog两种实现动态输入日期和时间的对话框 3 两组监测日期和时间改变的监听器 1 OnDateC
  • vue中使用百度地图 添加标记物,点击标记物弹窗,画运动轨迹,位置纠偏,逆地址解析

    在vue项目中使用百度地图 添加标记物 位置纠偏 信息弹窗 画轨迹 坐标转换 逆地址解析 参考vue baidu map开发文档 安装 npm install vue baidu map save 全局注册 在main js中引入以下代码