讲真,写下这个题目的时候,再想想自己整个实现功能的这1天时间,觉得自己好牛逼,啊哈哈哈,吹牛时间到了,进入正题……
本文从以下几个方面进行阐述。
- 1. 首先说一下业务需求是什么。
- 2. 然后说一下解决思路。
- 3. 最后是实现方式。
业务需求描述:
给客户做了一个物资管理系统,前台用的是vue+element-ui。因客户的物资大多是没有定位模块的,但又希望在地图上展示物资。因不能从定位模块获取经纬度数据进而在地图上进行展示,就只能自己手动操作,对物资进行位置设定,然后再在地图上进行展示。具体业务需求为:
当用户选中某条或某几条物资数据时,点击“设置定位”按钮,就会弹出一个弹出框,弹出框中会展示百度地图及一个“确定”按钮和一个“取消”按钮,当单击地图时,会在地图上进行位置标注。若位置标注完成,用户点击“确定”按钮即可对所需物资进行位置设置,若点击“取消”按钮,则不进行位置设置。
解决思路:
好了,业务需求如上所述。针对业务需求,需提出解决思路。
首先想到的是,在页面中写一个div容器的dialog以备存放地图,并给该div设置一个id,例如id="allmap",然后在js中通过var map = new BMap.Map("allmap");创建地图实例,再通过map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);设置地图中心点及地图展示级别即可。
这样实现时有一个问题:第一次点击“设置定位”按钮打开弹出框时,弹出框中并没有展示地图;第二次及后面点击按钮打开弹出框时,才会有地图展示出来。
这是因为,在页面打开时,弹出框并没有被页面加载,所以其id并不存在于页面的DOM树中,当第一次点击按钮打开弹出框时,通过var map = new BMap.Map("allmap");创建地图实例时并不能获取到allmap这个id代表的容器,所以地图第一次并不能展示。但第一次打开弹出框后,dialog中的allmap div已被页面加载过一次,所以第二次再通过var map = new BMap.Map("allmap");创建地图实例时,能够获取到allmap,进而就能够创建成功,所以地图能被展示。
为解决这个问题,经过调研,发现Vue Baidu Map可直接将center和zoom属性写进<baidu-map>标签中,如下所示:
<baidu-map :center="center" :zoom="zoom" @ready="handler"></baidu-map>
这样一来就不需要先加载某个容器id再在此id容器中创建地图实例了,就解决了第一次点击按钮打开弹出框时不显示地图的问题了。
具体实现代码如下图所示:
点击弹出框打开百度地图
需要注意的是,添加控件时,需要注册控件对应的组件,如下图所示:
注册控件组件
具体实现代码我直接贴出,就不再描述了。
methods: {
// 当选择项发生变化时会触发该事件
handleSelectionChange(val) {
var i = 0, valLen = val.length;
if (valLen == 0) {
this.locData.ids = 0;
} else {
for (i; i < valLen; i++) {
if (i == 0) {
this.locData.ids = val[i].id;
} else if (i > 0) {
this.locData.ids += "," + val[i].id;
}
}
}
},
// 当某一行被点击时会触发该事件 参数:row, event, column
getRowData(editEqu, event, column) {
this.$refs.equTable.toggleRowSelection(editEqu);
},
// 设置定位弹出框
setLoc(formName) {
if (this.locData.ids == 0) {
this.$message({
message: '请选中装备后再设置定位',
type: 'warning'
});
} else {
this.locDialog = true;
map.clearOverlays();
}
},
// 百度地图
mapReady ({BMap, map}) {
this.center.lng = 116.404;
this.center.lat = 39.915;
this.zoom = 15;
window.map = map; //将map变量存储在全局
},
// 地图点击事件
getClickInfo (e) {
map.clearOverlays();
var myMarker = new BMap.Marker(new BMap.Point(e.point.lng, e.point.lat));
map.addOverlay(myMarker);
this.locData.longitude = e.point.lng;
this.locData.latitude = e.point.lat;
},
// 设置定位确认
locSubmit(formName) {
if (this.locData.longitude == "") {
addOper.$message({
message: '请单击地图设置定位后再提交',
type: 'warning'
});
} else {
// 向后台提交locData数据
}
this.locDialog = false;
},
// 设置定位取消
locCancle(formName) {
map.clearOverlays();
this.locDialog = false;
}
}
这样就实现了所需的功能。最后贴一下实现功能时遇到的问题列表,供各位参考。
实现功能过程中的问题列表
methods里面的方法是根据也无需求写的,大家可参考。有任何问题留言给我哈。谢谢大家!
最后贴一个超实用链接:Vue Baidu Map