百度地图做电子围栏总结

2020-02-24 18:36:17

参考地址 百度地图做电子围栏总结

需求:在地图上画出围栏,设置围栏信息后保存,生成围栏列表。全选时,地图视野可看到全部的围栏区域,单独勾选会调整地图视野到当前勾选的围栏。围栏区域的中心点要显示围栏名称。


主要的难点(对于我而言)不在于画,而在于设置地图视野和围栏区域的中心点显示围栏名称,其实也不算难,主要是花比较多时间去看百度地图api,还有动手实践。(所以还是那句老话百度找不到答案就去看api文档,答案都在里面)。

以下主要说一下思路:

1.引入百度地图还有鼠标绘制管理类库DrawingManager


2.以下主要贴部分代码说明:


var electronitFence = {


//此处代码省略...


tableData: {},//保存每次list请求返回的数据

overlayObj: {},//保存图形对象(map)

  labelObj: {},//保存label对象(map)

  path: '',//当前新增围栏图形path

  pointArray: [],//坐标点数组用于调整地图视野范围

styleOptions: {//图形样式

    enableClicking: false,

    strokeColor: "blue",    //边线颜色。

    fillColor: "red",      //填充颜色。当参数为空时,圆形将没有填充效果。

    strokeWeight: 2,       //边线的宽度,以像素为单位。

    strokeOpacity: 0.6,    //边线透明度,取值范围0 - 1。

    fillOpacity: 0.5,      //填充的透明度,取值范围0 - 1。

    strokeStyle: 'solid' //边线的样式,solid或dashed。

  },

  init: function () {

    //此处代码省略...


    this.mapInit();

    this.bindEvent();


   //此处代码省略...


  },

  bindEvent:function(){

    //新增围栏

    $('#overlayType li').on('click', function () {

      var index = $(this).index();

      drawingManager.open();//开启地图的绘制模式

      if (index == 0) {

        drawingManager.setDrawingMode(BMAP_DRAWING_RECTANGLE);//绘制矩形

      } else if (index == 1) {

        drawingManager.setDrawingMode(BMAP_DRAWING_CIRCLE);//绘制圆形

      } else {

        drawingManager.setDrawingMode(BMAP_DRAWING_POLYGON);//绘制多边形

      }

    });

    //全选

    $('#checkAll').on('change', function () {

      if ($(this).is(":checked")) {//全选

        $('#page-list .checkItem').prop("checked", true);

        self.pointArray.length = 0;//清空pointArray

        self.curPageOverlayAllShow();//显示全部

        map.setViewport(self.pointArray); //调整视野

      } else {

        $('#page-list .checkItem').prop("checked", false);

        self.curPageOverlayAllHide();//隐藏全部

      }

    });

    //单选

    $('#page-list').on('change', '.checkItem', function () {

      if ($(this).is(":checked")) {

        if (!$('#checkAll').is(":checked")) {

          $('#checkAll').prop("checked", true);

        }

        self.pointArray.length = 0;//清空pointArray

        self.overlayShow(+$(this).val());//显示

        map.setViewport(self.pointArray); //调整视野

      } else {

        self.overlayHide(+$(this).val());//隐藏

        if ($('.checkItem:checked').length == 0) {

          $('#checkAll').prop("checked", false);

        }

      }

    });

  },

  /**

   * map初始化

   */

  mapInit: function () {

    var self = electronitFence;

    map = new BMap.Map('mapBox', {minZoom: 4, maxZoom: 16});

    map.centerAndZoom(new BMap.Point(116.4035, 39.915), 5);

    map.enableScrollWheelZoom();

    //实例化鼠标绘制工具(我不需要工具栏所以直接注释了)

    drawingManager = new BMapLib.DrawingManager(map, {

      isOpen: false, //是否开启绘制模式

      //enableDrawingTool: false, //是否显示工具栏

      //drawingToolOptions: {

      //anchor: BMAP_ANCHOR_TOP_RIGHT, //位置

      //  offset: new BMap.Size(5, 5) //偏离值

      //},

      circleOptions: self.styleOptions, //圆的样式

      polygonOptions: self.styleOptions, //多边形的样式

      rectangleOptions: self.styleOptions //矩形的样式

    });

    //添加鼠标绘制工具监听事件,用于获取绘制结果

    drawingManager.addEventListener('overlaycomplete', electronitFence.overlayComplete);

  },

  overlayComplete: function (e) {

    var self = electronitFence;

    var path = {};

    var bs = e.overlay.getBounds();//覆盖物对象的地理区域范围

    if (e.drawingMode == BMAP_DRAWING_CIRCLE) {//圆形

      path.radius = e.overlay.getRadius();//半径

      path.center = {};//中心点坐标

      path.center.lng = e.overlay.getCenter().lng;

      path.center.lat = e.overlay.getCenter().lat;

      path.path = [bs.getSouthWest(), bs.getNorthEast()];//****这个是重点:用来保存圆形的地理区域范围(Bounds)东北角和西南角坐标,用于地图视野调整

    } else {//矩形或多边形

      path.data = e.overlay.getPath();

      path.center = bs.getCenter();//****这个是重点:用于在图形中心点显示围栏名称

    }

    self.path = JSON.stringify(path);//这个会传给后端保存,请求回围栏列表数据中会一起返回,用于画出对应的图形


    //此处代码省略...

  },


  //此处代码省略...



  /**

   * 在地图上新建图形

   * @param id

   * @param type

   * @returns {*}

   */

  newOverlay: function (id, type) {

    var self = electronitFence;

    var overlay = null;

    var path = JSON.parse(self.tableData[id].coordinate);//tableData[id]是围栏列表数据,coordinate保存的是上面的path 值

    if (type == 2) {//圆形

      var mPoint = new BMap.Point(path.center.lng, path.center.lat);

      overlay = new BMap.Circle(mPoint, path.radius, style);

      self.pointArray = self.pointArray.concat(path.path);

    } else {//矩形或四边形

      overlay = new BMap.Polygon(path.data, style);

      self.pointArray = self.pointArray.concat(path.data);

    }

    self.overlayObj[id] = {};

    self.overlayObj[id].overlay = overlay;//添加到overlayObj

    map.addOverlay(overlay);

    //创建label,显示围栏名称

    var opts = {position: path.center};

    var label = new BMap.Label(self.tableData[id].fenceName, opts);

    label.setStyle(self.labelStyle);

    label.addEventListener('click', function () {

      var carPath = JSON.parse(self.tableData[id].coordinate);//坐标点

      self.pointArray.length = 0;

      if (type == 2) {//圆

        self.pointArray = carPath.path;

      } else {

        self.pointArray = carPath.data;

      }

      map.setViewport(self.pointArray);    //调整视野

    });

    self.labelObj[id] = {};

    self.labelObj[id].label = label;

    map.addOverlay(label);

  },

  /**

   * 图形显示

   * @param id

   */

  overlayShow: function (id) {

    var self = electronitFence;

    var type = self.tableData[id].coordinateType;//图形类型

    var path = JSON.parse(self.tableData[id].coordinate);//坐标点

    if (self.overlayObj[id]) {//如果overlayObj中有就show

      self.overlayObj[id].overlay.show();

      self.labelObj[id].label.setContent(self.tableData[id].fenceName);

      self.labelObj[id].label.show();

      if (type != 2) {//圆

        self.pointArray = self.pointArray.concat(path.data);

      } else {

        self.pointArray = self.pointArray.concat(path.path);

      }

    } else {//如果overlayObj中无就new一个

      self.newOverlay(id, type);

    }

  },

  /**

   * 图形隐藏

   * @param id

   */

  overlayHide: function (id) {

    electronitFence.overlayObj[id].overlay.hide();

    electronitFence.labelObj[id].label.hide();

  },

/**

   * 显示当前页所有图形

   */

  curPageOverlayAllShow: function () {

    $('.checkItem').each(function () {

      electronitFence.overlayShow(+$(this).val());

    })

  },

  /**

   * 隐藏当前页所有图形

   */

  curPageOverlayAllHide: function () {

    var self = electronitFence;

    $('.checkItem').each(function () {

      var id = +$(this).val();

      if (self.overlayObj[id]) {

        self.overlayHide(id);

      }

    })

  },


 //此处代码省略...

}

$(function () {

  electronitFence.init();

});


总结:可能有人会问为什么不在newOverlay的时候getSouthWest(),getNorthEast(),getCenter()。一开始我也这么做但是根据返回的数据坐标点新建overlay生成的overlay.getBounds()执行报错。目前还不知道原因。。。隐藏overlay,很多人可能都喜欢用map.removeOverlay()的方法直接删掉overlay,下次显示再new。我发现如果overlay很多的时候会new得很慢,如果每次new的时候保存在一个对象里面,直接通过overlay.show(),overlay.hide()显示隐藏会快很多。



  • 2020-12-01 16:19:26

    vue中动画分布解析

    enter, enter-active, enter-active-to, (开始 进入阶段的)第1帧 属性值,到 (默认属性值 的过渡阶段),移除enter动画, leave, leave-active, leave-active-to (开始 离开 阶段的)第1帧 默认属性值,到 (属性值 的过渡阶段),移除leave动画

  • 2020-12-01 16:21:47

    Meteor与express结合开发

    Meteor本质上是一个已经公开了连接 http服务器的节点应用程序,这意味着您可以像下面这样定义服务器路由:,如果您坚持使用Express,则可以将Express路由注册为Connect中间件,如下所示:

  • 2020-12-01 16:25:32

    nuxtjs引入jquery

    nuxt引入jQuery库 nuxtjs如何添加 Webpack 插件?

  • 2020-12-01 16:43:37

    fieldset标签做输入框

    比如 vuetify中的 input组件,就用到了fieldset做边框, 这个时候我们想改边框,却找不到border,因为fieldset是靠color来修改边框颜色的。

  • 2020-12-01 17:25:39

    axios并发操作

    很多时候,我们需要同时向后端进行多个请求,当所有请求都返回数据后,再进行一些操作。