vue中使用百度地图 添加标记物,点击标记物弹窗,画运动轨迹,位置纠偏,逆地址解析
在vue项目中使用百度地图,添加标记物、信息弹窗、动态画轨迹首先安装<div id="allmap"><baidu-map class="bm-view":center="center"@ready="handler"></baidu-map></div><style scoped lang="scss">#allmap {width:
·
在vue项目中使用百度地图,添加标记物、位置纠偏、信息弹窗、画轨迹,坐标转换,逆地址解析
参考vue-baidu-map开发文档
- 安装 npm install vue-baidu-map --save,
- 全局注册,在main.js中引入以下代码
import BaiduMap from ‘vue-baidu-map’
Vue.use(BaiduMap, {
ak: ‘申请的百度地图ak’
}) - 页面引用
<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指代,逆地址解析,坐标转换(百度地图位置纠偏) 等。
- 调用接口获取经纬度集合,经纬度坐标为百度坐标的不用转换,为GPS坐标等其它坐标类型时需要转换为百度坐标;
- 获取到经纬度集合数据后,进行地图初始化,设置地图中心位置、缩放比例、是否可鼠标滚动缩放,添加标记点等;
- 标记点上添加点击事件并弹窗信息。
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坐标,转换的地方有注释。
- 起点位置,调用一次接口获取起点并进行标记;
- 设置定时器调用接口获取下一个经纬度坐标,定时器设置时长根据后端实时获取到的数据进行设置,要比后端时间稍长,同时要处理后端没有获取到经纬度或者无效经纬度的情况(比如用前一个点代替);
- 有2个经纬度坐标就可以进行划线;
- 设置当前位置的marker,为矢量小车图标,同时根据当前划线的角度纠正小车图标头部朝向前进方向,不需要区分方向的图标则不用进行角度处理;
- 页面关闭或者长时间不操作页面时注意定时器的清除。
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),逆地址解析时会不起作用。
更多推荐
已为社区贡献5条内容
所有评论(0)