在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),逆地址解析时会不起作用。

Logo

前往低代码交流专区

更多推荐