更多文章可关注个人我的博客: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时都须要从新监听覆盖物的宽高。