您现在的位置是:首页 > 技术教程 正文

百度地图BMap vue 绘制电子围栏--模拟矩形编辑--测距工具

admin 阅读: 2024-04-01
后台-插件-广告管理-内容页头部广告(手机)

需求:由于项目需求,需要集成百度地图并会有相关坐标点展示,且需要绘制围栏等等操作。

需求开发遇到的坑:==>由于前期集成了vue-baidu-map 官方地址 具体集成请自行参考百度,页面地图是使用BMap,后面打算引入百度地图绘制辅助工具BMapGLLib,结果并不能正常显示绘制工具和进行绘制;仔细分析后发现是集成的地图不匹配。(辅助工具BMapGLLib只能用于创建的BMapGL地图,而BMap不能使用),BMapGLLib工具实在是好用,可自动开启编辑(主要是矩形编辑的问题)。因此只能另开途径进行开发。

注意:以下方法皆是居于BMap实现的,如引入百度地图为BMapGL,请自行参考百度地图api

open | 百度地图API SDK   辅助工具目录

解决方案步骤:

1、在vue项目的index.html里面加上以下代码: 这个是BMap的引入

2、继续引入绘制工具,适用于BMap地图

 

   

   

   

3、创建地图,具体创建方法参考自己项目,本处只是例子参考

  1. <script>
  2. createMap(lgt, lat) {
  3. // this.maploading=true;
  4. this.map = new BMap.Map("XXX", { enableMapClick: false }) // 创建Map实例空间为BMap(鼠标右键控制倾斜角度)
  5. this.map.centerAndZoom(new BMap.Point(lgt, lat), 11) // 初始化地图,设置中心点坐标和地图级别
  6. this.map.enableScrollWheelZoom(true)// 开启鼠标滚轮缩放
  7. },
  8. script>

4、通过按钮点击进行圆形,矩形,多边形进行选择绘制,具体参考代码,本代码是放在methods下

  1. <script>
  2. //绘制围栏(圆形,矩形,多边形)
  3. createEnS(drawingType){
  4. let self=this
  5. //画图样式
  6. let styleOptions = {
  7. strokeColor:"rgb(27, 167, 229)", //边线颜色。
  8. fillColor:"rgb(27, 167, 229)", //填充颜色。当参数为空时,圆形将没有填充效果。
  9. strokeWeight: 2, //边线的宽度,以像素为单位。
  10. strokeOpacity: 0.8, //边线透明度,取值范围0 - 1。
  11. fillOpacity: 0.3, //填充的透明度,取值范围0 - 1。
  12. strokeStyle: 'dashed', //边线的样式,solid或dashed。
  13. };
  14. //生成鼠标绘制工具
  15. var drawingManager = new BMapLib.DrawingManager(self.map , {
  16. isOpen: false,
  17. // drawingType: BMAP_DRAWING_CIRCLE,
  18. // enableDrawingTool:false, //是否显示工具栏
  19. // drawingToolOptions: {
  20. // anchor: BMAP_ANCHOR_TOP_LEFT,
  21. // offset: new BMap.Size(5, 50),
  22. // drawingModes:[
  23. // // BMAP_DRAWING_POLYGON,
  24. // BMAP_DRAWING_CIRCLE
  25. // ]
  26. // },
  27. // enableCalculate: true, // 绘制是否进行测距测面
  28. enableSorption: true, // 是否开启边界吸附功能
  29. sorptiondistance: 20, // 边界吸附距离
  30. //图形默认样式
  31. circleOptions: styleOptions,
  32. polylineOptions: styleOptions,
  33. polygonOptions: styleOptions,
  34. rectangleOptions: styleOptions
  35. });
  36. let drawingMode
  37. if(drawingType=='circular'){
  38. drawingMode=BMAP_DRAWING_CIRCLE
  39. }else if(drawingType=='rectangular'){
  40. drawingMode=BMAP_DRAWING_RECTANGLE
  41. }else if(drawingType=='polygon'){
  42. drawingMode=BMAP_DRAWING_POLYGON
  43. }
  44. drawingManager.setDrawingMode(drawingMode)
  45. drawingManager.open()
  46. //判断图案类型
  47. let overlaycomplete = function(e){
  48. drawingManager.close();
  49. //判断画图的类型
  50. if(e.drawingMode=='circle'){
  51. //圆形
  52. let radius=e.overlay.getRadius();//圆半径
  53. let circlecenter=e.overlay.getCenter(); //圆心坐标
  54. //开启编辑
  55. e.overlays.enableEditing()
  56. //监听编辑
  57. e.overlays.addEventListener("lineupdate",function(e){
  58. e.overlays.center=e.target.point; //圆心
  59. e.overlays.radius=e.target.xa; //半径
  60. });
  61. }else if (e.drawingMode=='rectangle') {
  62. //矩形,特殊--由四个标记点带动编辑的改变
  63. var myIcon = new BMap.Icon(self.url+'checkbox.png', new BMap.Size(13,13));//增加icon,可以截取百度默认的选择框增加相似度
  64. let startPoint
  65. let endPoint
  66. let startPointTwo
  67. let endPointTwo
  68. e.overlay.getPath().forEach((item,index)=>{
  69. if (index==0) {//左上角点
  70. startPoint=item
  71. let markerStart= new BMap.Marker(item,{icon:myIcon})
  72. markerStart.enableDragging()
  73. markerStart.addEventListener('dragging',(target)=>{
  74. startPoint = target.point
  75. e.overlay.setPath(this._getRectanglePoint(target.point,endPoint));
  76. })
  77. self.map.addOverlay(markerStart);
  78. }else if (index==2) {//右下角点
  79. endPoint=item
  80. let markerEnd = new BMap.Marker(item,{icon:myIcon})
  81. markerEnd.enableDragging()
  82. markerEnd.addEventListener('dragging',(target)=>{
  83. endPoint=target.point
  84. e.overlay.setPath(this._getRectanglePoint(startPoint,target.point));
  85. })
  86. self.map.addOverlay(markerEnd);
  87. }
  88. })
  89. }else{
  90. //多边形
  91. //其它图形打开编辑功能
  92. e.overlay.enableEditing();
  93. e.overlay.addEventListener("lineupdate",function(p){
  94. })
  95. }
  96. };
  97. //监听整个绘制围栏方法
  98. drawingManager.addEventListener('overlaycomplete', overlaycomplete);
  99. },
  100. _getRectanglePoint(startPoint,endPoint){
  101. return [
  102. new BMap.Point(startPoint.lng,startPoint.lat),
  103. new BMap.Point(endPoint.lng,startPoint.lat),
  104. new BMap.Point(endPoint.lng,endPoint.lat),
  105. new BMap.Point(startPoint.lng,endPoint.lat)
  106. ];
  107. }
  108. script>

注意:由于矩形特殊,且new BMapLib.DrawingManager绘制工具没有自带的矩形编辑功能,只能通过捷径进行模拟矩形绘制,本文只进行两个顶点的模拟拉动,如想四顶点一起模拟请自行编写(思路一致,处理好拉动一个顶点其余三顶点逻辑关系就好==>可参考如下方法:虽然比较笨,但可实现,如有高效便捷方法请分享呗)

模拟绘制矩形编辑四顶点关系大概逻辑:

  1. <script>
  2. /*只是为了好看才用写在方法内,具体结合上文打开编辑后模拟的矩形顶点监听器内,
  3. e表示模拟矩形顶点Marker移动属性,index为模拟矩形顶点的顺序(左上角为0,
  4. 右上角为1,右下角为2,左下角为3),具体传参结合上文模拟矩形顶点编辑,
  5. 此处只提供较笨的大概逻辑;polygonPath表示绘制矩形的四顶点坐标==>
  6. e.overlay.getPath()
  7. 注意:polygonPath计算完坐标后返回给上文e.overlay.setPath
  8. (rectangularDragend(e, index));重新赋值模拟矩形坐标才能实现矩形移动,当然,
  9. 其余模拟顶点Marker也要重新更新坐标,请自行编写代码更新*/
  10. rectangularDragend(e, index,polygonPath) {
  11. let self = this
  12. let newArr = [], point0, point1, point2, point3
  13. switch (index) {
  14. case 0:
  15. point2 = polygonPath[2]
  16. point0 = e.point
  17. point1 = { lng: polygonPath[2].lng, lat: e.point.lat }
  18. point3 = { lng: e.point.lng, lat: polygonPath[2].lat }
  19. break;
  20. case 1:
  21. point0 = { lng: polygonPath[3].lng, lat: e.point.lat }
  22. point3 = polygonPath[3]
  23. point1 = e.point
  24. point2 = { lng: e.point.lng, lat: polygonPath[3].lat }
  25. break;
  26. case 2:
  27. point0 = polygonPath[0]
  28. point1 = { lng: e.point.lng, lat: polygonPath[0].lat }
  29. point2 = e.point
  30. point3 = { lng: polygonPath[0].lng, lat: e.point.lat }
  31. break;
  32. case 3:
  33. point0 = { lng: e.point.lng, lat: polygonPath[1].lat }
  34. point1 = polygonPath[1]
  35. point2 = { lng: polygonPath[1].lng, lat: e.point.lat }
  36. point3 = e.point
  37. break;
  38. }
  39. self.$nextTick(() => { //self.$nextTick可去除,根据实际情况
  40. newArr.push(point0)
  41. newArr.push(point1)
  42. newArr.push(point2)
  43. newArr.push(point3)
  44. //此处可返回newArr给调用方法
  45. return newArr
  46. })
  47. },
  48. script>

5、鼠标测距工具,由于步骤2处已引入相关控件,直接使用即可,代码如下:

  1. <script>
  2. // 测距工具
  3. distanceTool(){
  4. var distance= new BMapLib.DistanceTool(this.map)
  5. distance.open()
  6. // //监听测距尺鼠标右击测距尺添加完成的时候触发的事件
  7. distance.addEventListener('drawend', function(e) {
  8. //自身项目处理逻辑
  9. });
  10. },
  11. script>

矩形编辑模拟情况效果如下:

 本人开发过程经历的一个大坑分享:

      前期发现BMap无法使用辅助工具BMapGLLib后,考虑过辅助工具BMapLib,但百度一番没找到辅助工具BMapLib下矩形编辑的问题,由于第一次接触vue和百度地图(我是写后端Java的,被项目经理拉来帮忙干前端vue),所以开始实现思路是利用鼠标点击、移动和结合vue-baidu-map官网的圆形,多边形绘制方法进行手动绘制==>即编写自己的控件,后面经历三天后完成控件的编写,成功实现了圆形,矩形,多边形各自绘制和编辑,但后面本人发现了一个大坑;

==================================大坑========================

        由于vue-baidu-map是需要操作DOM元素进行地图上添加各种覆盖物,而我手动编写的控件就是基于vue-baidu-map进行开发,当地图上出现大量的覆盖物时,此时进行电子围栏的绘制(圆形,矩形,多边形)都会超级卡顿,让人一看就觉得是bug;后来才发现是手动绘制不断更新坐标位置和覆盖物位置大量操作了DOM元素导致的,只能放弃自编的控件而采用百度地图给出的控件辅助工具BMapLib,进行一定程度功能修改。一次难忘的制造bug经历。。。。。

自己吐槽下,原本是想把BMap更改为BMapGL地图,害怕更改后前面编写的信息窗口,标志,路书(轨迹)等出现问题且能力有限不知到如何全局更改只能放弃了。

至此本文结束。

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索