需求:由于项目需求,需要集成百度地图并会有相关坐标点展示,且需要绘制围栏等等操作。
需求开发遇到的坑:==>由于前期集成了vue-baidu-map 官方地址 具体集成请自行参考百度,页面地图是使用BMap,后面打算引入百度地图绘制辅助工具BMapGLLib,结果并不能正常显示绘制工具和进行绘制;仔细分析后发现是集成的地图不匹配。(辅助工具BMapGLLib只能用于创建的BMapGL地图,而BMap不能使用),BMapGLLib工具实在是好用,可自动开启编辑(主要是矩形编辑的问题)。因此只能另开途径进行开发。
注意:以下方法皆是居于BMap实现的,如引入百度地图为BMapGL,请自行参考百度地图api
open | 百度地图API SDK 辅助工具目录
解决方案步骤:
1、在vue项目的index.html里面加上以下代码: 这个是BMap的引入
<script type="text/javascript" src="//api.map.baidu.***/api?v=3.0&ak=您的密钥"></script>
2、继续引入绘制工具,适用于BMap地图
<!--绘制工具-->
<script type="text/javascript" src="http://api.map.baidu.***/library/DrawingManager/1.4/src/DrawingManager_min.js"></script>
<script type="text/javascript" src="http://api.map.baidu.***/library/DrawingManager/1.4/src/DrawingManager_min.css"></script>
<!-- 测距工具 -->
<script type="text/javascript" src="http://api.map.baidu.***/library/DistanceTool/1.2/src/DistanceTool_min.js"></script>
3、创建地图,具体创建方法参考自己项目,本处只是例子参考
<script>
createMap(lgt, lat) {
// this.maploading=true;
this.map = new BMap.Map("XXX", { enableMapClick: false }) // 创建Map实例空间为BMap(鼠标右键控制倾斜角度)
this.map.centerAndZoom(new BMap.Point(lgt, lat), 11) // 初始化地图,设置中心点坐标和地图级别
this.map.enableScrollWheelZoom(true)// 开启鼠标滚轮缩放
},
</script>
4、通过按钮点击进行圆形,矩形,多边形进行选择绘制,具体参考代码,本代码是放在methods下
<script>
//绘制围栏(圆形,矩形,多边形)
createEnS(drawingType){
let self=this
//画图样式
let styleOptions = {
strokeColor:"rgb(27, 167, 229)", //边线颜色。
fillColor:"rgb(27, 167, 229)", //填充颜色。当参数为空时,圆形将没有填充效果。
strokeWeight: 2, //边线的宽度,以像素为单位。
strokeOpacity: 0.8, //边线透明度,取值范围0 - 1。
fillOpacity: 0.3, //填充的透明度,取值范围0 - 1。
strokeStyle: 'dashed', //边线的样式,solid或dashed。
};
//生成鼠标绘制工具
var drawingManager = new BMapLib.DrawingManager(self.map , {
isOpen: false,
// drawingType: BMAP_DRAWING_CIRCLE,
// enableDrawingTool:false, //是否显示工具栏
// drawingToolOptions: {
// anchor: BMAP_ANCHOR_TOP_LEFT,
// offset: new BMap.Size(5, 50),
// drawingModes:[
// // BMAP_DRAWING_POLYGON,
// BMAP_DRAWING_CIRCLE
// ]
// },
// enableCalculate: true, // 绘制是否进行测距测面
enableSorption: true, // 是否开启边界吸附功能
sorptiondistance: 20, // 边界吸附距离
//图形默认样式
circleOptions: styleOptions,
polylineOptions: styleOptions,
polygonOptions: styleOptions,
rectangleOptions: styleOptions
});
let drawingMode
if(drawingType=='circular'){
drawingMode=BMAP_DRAWING_CIRCLE
}else if(drawingType=='rectangular'){
drawingMode=BMAP_DRAWING_RECTANGLE
}else if(drawingType=='polygon'){
drawingMode=BMAP_DRAWING_POLYGON
}
drawingManager.setDrawingMode(drawingMode)
drawingManager.open()
//判断图案类型
let overlay***plete = function(e){
drawingManager.close();
//判断画图的类型
if(e.drawingMode=='circle'){
//圆形
let radius=e.overlay.getRadius();//圆半径
let circlecenter=e.overlay.getCenter(); //圆心坐标
//开启编辑
e.overlays.enableEditing()
//监听编辑
e.overlays.addEventListener("lineupdate",function(e){
e.overlays.center=e.target.point; //圆心
e.overlays.radius=e.target.xa; //半径
});
}else if (e.drawingMode=='rectangle') {
//矩形,特殊--由四个标记点带动编辑的改变
var myIcon = new BMap.Icon(self.url+'checkbox.png', new BMap.Size(13,13));//增加icon,可以截取百度默认的选择框增加相似度
let startPoint
let endPoint
let startPointTwo
let endPointTwo
e.overlay.getPath().forEach((item,index)=>{
if (index==0) {//左上角点
startPoint=item
let markerStart= new BMap.Marker(item,{icon:myIcon})
markerStart.enableDragging()
markerStart.addEventListener('dragging',(target)=>{
startPoint = target.point
e.overlay.setPath(this._getRectanglePoint(target.point,endPoint));
})
self.map.addOverlay(markerStart);
}else if (index==2) {//右下角点
endPoint=item
let markerEnd = new BMap.Marker(item,{icon:myIcon})
markerEnd.enableDragging()
markerEnd.addEventListener('dragging',(target)=>{
endPoint=target.point
e.overlay.setPath(this._getRectanglePoint(startPoint,target.point));
})
self.map.addOverlay(markerEnd);
}
})
}else{
//多边形
//其它图形打开编辑功能
e.overlay.enableEditing();
e.overlay.addEventListener("lineupdate",function(p){
})
}
};
//监听整个绘制围栏方法
drawingManager.addEventListener('overlay***plete', overlay***plete);
},
_getRectanglePoint(startPoint,endPoint){
return [
new BMap.Point(startPoint.lng,startPoint.lat),
new BMap.Point(endPoint.lng,startPoint.lat),
new BMap.Point(endPoint.lng,endPoint.lat),
new BMap.Point(startPoint.lng,endPoint.lat)
];
}
</script>
注意:由于矩形特殊,且new BMapLib.DrawingManager绘制工具没有自带的矩形编辑功能,只能通过捷径进行模拟矩形绘制,本文只进行两个顶点的模拟拉动,如想四顶点一起模拟请自行编写(思路一致,处理好拉动一个顶点其余三顶点逻辑关系就好==>可参考如下方法:虽然比较笨,但可实现,如有高效便捷方法请分享呗)
模拟绘制矩形编辑四顶点关系大概逻辑:
<script>
/*只是为了好看才用写在方法内,具体结合上文打开编辑后模拟的矩形顶点监听器内,
e表示模拟矩形顶点Marker移动属性,index为模拟矩形顶点的顺序(左上角为0,
右上角为1,右下角为2,左下角为3),具体传参结合上文模拟矩形顶点编辑,
此处只提供较笨的大概逻辑;polygonPath表示绘制矩形的四顶点坐标==>
e.overlay.getPath()
注意:polygonPath计算完坐标后返回给上文e.overlay.setPath
(rectangularDragend(e, index));重新赋值模拟矩形坐标才能实现矩形移动,当然,
其余模拟顶点Marker也要重新更新坐标,请自行编写代码更新*/
rectangularDragend(e, index,polygonPath) {
let self = this
let newArr = [], point0, point1, point2, point3
switch (index) {
case 0:
point2 = polygonPath[2]
point0 = e.point
point1 = { lng: polygonPath[2].lng, lat: e.point.lat }
point3 = { lng: e.point.lng, lat: polygonPath[2].lat }
break;
case 1:
point0 = { lng: polygonPath[3].lng, lat: e.point.lat }
point3 = polygonPath[3]
point1 = e.point
point2 = { lng: e.point.lng, lat: polygonPath[3].lat }
break;
case 2:
point0 = polygonPath[0]
point1 = { lng: e.point.lng, lat: polygonPath[0].lat }
point2 = e.point
point3 = { lng: polygonPath[0].lng, lat: e.point.lat }
break;
case 3:
point0 = { lng: e.point.lng, lat: polygonPath[1].lat }
point1 = polygonPath[1]
point2 = { lng: polygonPath[1].lng, lat: e.point.lat }
point3 = e.point
break;
}
self.$nextTick(() => { //self.$nextTick可去除,根据实际情况
newArr.push(point0)
newArr.push(point1)
newArr.push(point2)
newArr.push(point3)
//此处可返回newArr给调用方法
return newArr
})
},
</script>
5、鼠标测距工具,由于步骤2处已引入相关控件,直接使用即可,代码如下:
<script>
// 测距工具
distanceTool(){
var distance= new BMapLib.DistanceTool(this.map)
distance.open()
// //监听测距尺鼠标右击测距尺添加完成的时候触发的事件
distance.addEventListener('drawend', function(e) {
//自身项目处理逻辑
});
},
</script>
矩形编辑模拟情况效果如下:
本人开发过程经历的一个大坑分享:
前期发现BMap无法使用辅助工具BMapGLLib后,考虑过辅助工具BMapLib,但百度一番没找到辅助工具BMapLib下矩形编辑的问题,由于第一次接触vue和百度地图(我是写后端Java的,被项目经理拉来帮忙干前端vue),所以开始实现思路是利用鼠标点击、移动和结合vue-baidu-map官网的圆形,多边形绘制方法进行手动绘制==>即编写自己的控件,后面经历三天后完成控件的编写,成功实现了圆形,矩形,多边形各自绘制和编辑,但后面本人发现了一个大坑;
==================================大坑========================
由于vue-baidu-map是需要操作DOM元素进行地图上添加各种覆盖物,而我手动编写的控件就是基于vue-baidu-map进行开发,当地图上出现大量的覆盖物时,此时进行电子围栏的绘制(圆形,矩形,多边形)都会超级卡顿,让人一看就觉得是bug;后来才发现是手动绘制不断更新坐标位置和覆盖物位置大量操作了DOM元素导致的,只能放弃自编的控件而采用百度地图给出的控件辅助工具BMapLib,进行一定程度功能修改。一次难忘的制造bug经历。。。。。
自己吐槽下,原本是想把BMap更改为BMapGL地图,害怕更改后前面编写的信息窗口,标志,路书(轨迹)等出现问题且能力有限不知到如何全局更改只能放弃了。
至此本文结束。