1. 程式人生 > >百度地圖自定義覆蓋物手機端新增點選事件無效

百度地圖自定義覆蓋物手機端新增點選事件無效

最近在做百度地圖新增自定義覆蓋物時,遇到一個問題。起先參照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時都需要重新監聽覆蓋物的寬高。