百度地图自定义覆盖物手机端添加点击事件无效

更多文章可关注个人我的博客:https://seven777777.github.io/myblog/javascript

最近在作百度地图添加自定义覆盖物时,遇到一个问题。起先参照api都很顺利,可是当我在给自定义的覆盖物添加点击事件时,问题来了:没法触发。html

去网上找了一些解决方案,包括注册点击事件之类的,都没有解决。java

以后无心发现,当把调试模式切出手机模式时,点击事件就可以正确的触发,由此得出结论,问题点在于页面是在手机端运行,因此尝试写入了手机端的常见事件,如touch,touchstart…,依旧没法解决,查了下发现是因为百度地图手机端默认的事件是拖动事件,屏蔽其余事件。git

说一下最终解决方案吧,参考了这篇文章github

引入js:http://api.map.baidu.com/library/EventWrapper/1.2/src/EventWrapper.jsweb

使用:api

BMapLib.EventWrapper.addDomListener(mySquare._div, "touchend", function(e){
    //...点击操做
});

tip:BMapLib是这个库的命名空间,BMap全部library都在bMapLib命名空间之下数组

下面贴出个人代码:app

//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){
        //事件处理
    });
});

以上。dom

须要再说明一点的是另外一个问题:除了点击事件以外,我发现每次放大缩小地图的时候,覆盖都会先偏移一下才能回到正确的位置。

在封装draw事件时,由于是移动端,因此为了让我自定义的图片的底部中间位置对准point,没法经过确切的px值来计算,因此我使用了自定义图片的clientWidth和clientHeight。
但因为每次放大缩小地图时都会触发draw事件,而从新绘制开始clientWidth和clientHeight会变成0,因此位置会出现误差。

解决方法就是上面代码写的那样,在初始化方法里面定义clientWidth和clientHeight,而后在draw函数里面引用,这样就能够保证不用每次draw时都须要从新监听覆盖物的宽高。

搴芳拾梦
欢迎关注的个人我的公众号【搴芳拾梦】