百度地圖自定義覆蓋物手機端新增點選事件無效
阿新 • • 發佈:2019-01-30
最近在做百度地圖新增自定義覆蓋物時,遇到一個問題。起先參照api都很順利,但是當我在給自定義的覆蓋物新增點選事件時,問題來了:無法觸發。
去網上找了一些解決方案,包括註冊點選事件之類的,都沒有解決。
之後無意發現,當把除錯模式切出手機模式時,點選事件就能夠正確的觸發,由此得出結論,問題點在於頁面是在手機端執行,所以嘗試寫入了手機端的常見事件,如touch,touchstart…,依舊無法解決,查了下發現是由於百度地圖手機端預設的事件是拖動事件,遮蔽其他事件。
說一下最終解決方案吧,參考了這篇文章。
使用:
BMapLib.EventWrapper.addDomListener(mySquare._div, "touchend" , function(e){
//...點選操作
});
tip:BMapLib是這個庫的名稱空間,BMap所有library都在bMapLib名稱空間之下
下面貼出我的程式碼:
//html
<div class="bdMap_wrap" id="bdMap_pic"></div>//地圖容器
//封裝的js:customizeOverlay.js
/*
* 定義自定義覆蓋物的建構函式
* 引數:(你可以對應設定你自己需要傳的引數)
* point:座標點
* text:提示文字
* num:座標點上的數字標號
*/
function customizeOverlay (point,text,num){
this._point=point;
this._text=text;
this._num=num;
};
// 繼承API的BMap.Overlay
customizeOverlay.prototype = new BMap.Overlay();
// 實現初始化方法
customizeOverlay.prototype.initialize = function (map) {
// 儲存map物件例項
this._map = map;
// 建立div元素,作為自定義覆蓋物的容器
let div = document.createElement("div");
$(div).addClass('map_point_icon');//提前寫好自定義覆蓋的樣式,然後這邊用js建立dom
div.innerHTML=this._num;
let label = document.createElement("div");
$(label).addClass('label_box');
label.innerHTML=this._text;
div.appendChild(label);
// 將div新增到覆蓋物容器中
map.getPanes().markerPane.appendChild(div);
// 儲存div例項
this._div = div;
this._cwidth=this._div.clientWidth;
this._cheight=this._div.clientHeight;
// 需要將div元素作為方法的返回值,當呼叫該覆蓋物的show、
// hide方法,或者對覆蓋物進行移除時,API都將操作此元素。
return div;
}
// 實現繪製方法
customizeOverlay.prototype.draw = function () {
// 根據地理座標轉換為畫素座標,並設定給容器
let position = this._map.pointToOverlayPixel(this._point);
this._div.style.left = position.x - this._cwidth/2 + "px";
this._div.style.top = position.y - this._cheight + "px";
}
//頁面呼叫,html檔案底部
//引入需要的js
//...
<script type="text/javascript" src="http://api.map.baidu.com/library/EventWrapper/1.2/src/EventWrapper.js"></script>
<script type="text/javascript" src="customizeOverlay.js"></script>
//...
let map = new BMap.Map("bdMap_pic");//建立例項
let point = new BMap.Point(121.486705,31.245197); // 建立點座標
map.centerAndZoom(point, 11);// 初始化地圖,設定中心點座標和地圖級別
map.setMapStyle({style:'light'});//設定地圖主題
map.enableScrollWheelZoom(true);//開啟滑鼠滾輪縮放
map.setMinZoom(9);
map.setMaxZoom(18);
let pointData=[//用來測試的point,實際開發會從後臺讀取
{
name:'豫園',
value1:121.498981,
value2:31.232772
},
{
name:'靜安寺',
value1:121.451697,
value2:31.229792
},
{
name:'上海大寧劇院',
value1:121.463457,
value2:31.290447
}
];
//遍歷pointData陣列,新增多個自定義覆蓋物
pointData.forEach((item,index)=>{
let mySquare=new customizeOverlay(new BMap.Point(item.value1,item.value2), item.name, index+1);
map.addOverlay(mySquare);
BMapLib.EventWrapper.addDomListener(mySquare._div, "touchend", function(e){
//事件處理
});
});
以上。
需要再說明一點的是另一個問題:除了點選事件之外,我發現每次放大縮小地圖的時候,覆蓋都會先偏移一下才能回到正確的位置。
在封裝draw事件時,因為是移動端,所以為了讓我自定義的圖片的底部中間位置對準point,無法通過確切的px值來計算,所以我使用了自定義圖片的clientWidth和clientHeight。
但由於每次放大縮小地圖時都會觸發draw事件,而重新繪製開始clientWidth和clientHeight會變成0,所以位置會出現偏差。
解決方法就是上面程式碼寫的那樣,在初始化方法裡面定義clientWidth和clientHeight,然後在draw函式裡面引用,這樣就可以保證不用每次draw時都需要重新監聽覆蓋物的寬高。