百度地圖做電子圍欄總結
阿新 • • 發佈:2019-01-08
需求:在地圖上畫出圍欄,設定圍欄資訊後儲存,生成圍欄列表。全選時,地圖視野可看到全部的圍欄區域,單獨勾選會調整地圖視野到當前勾選的圍欄。圍欄區域的中心點要顯示圍欄名稱。
主要的難點(對於我而言)不在於畫,而在於設定地圖視野和圍欄區域的中心點顯示圍欄名稱,其實也不算難,主要是花比較多時間去看百度地圖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()顯示隱藏會快很多。