1. 程式人生 > >百度地圖做電子圍欄總結

百度地圖做電子圍欄總結

需求:在地圖上畫出圍欄,設定圍欄資訊後儲存,生成圍欄列表。全選時,地圖視野可看到全部的圍欄區域,單獨勾選會調整地圖視野到當前勾選的圍欄。圍欄區域的中心點要顯示圍欄名稱。
這裡寫圖片描述

主要的難點(對於我而言)不在於畫,而在於設定地圖視野和圍欄區域的中心點顯示圍欄名稱,其實也不算難,主要是花比較多時間去看百度地圖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()顯示隱藏會快很多。