百度地图覆盖物点击事件

最近在项目中使用百度地图的自定义覆盖物时发现在手机浏览器下click无法触发,虽然有touchstart,touchmove,touchend等方法,但都不适合项目逻辑。

下面的代码我简单地定义了一个红色矩形div,给它一个click事件,添加到地图中

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <style type="text/css">
        body, html
        {
            width: 100%;
            height: 100%;
            overflow: hidden;
            margin: 0;
            font-family: "微软雅黑";
        }
        #allmap
        {
            margin: 0 0 3px;
            height: 100%;
        }
        .customOverlay
        {
            background:#ff0000;
            width:100px;height:100px;
            position:absolute;
         }
    </style>
    <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=d48dRYg4j4K81puarHtLXBheW40bG1HW"></script>
    <title>2种地图</title>
</head>
<body>
    <div id="allmap">
    </div>
</body>
</html>
<script type="text/javascript">

    /*
    *  自定义标注
    */
    var CustomOverlay = function (point, options) {
        this._point = point;
        this.opts = options;
    }
    // 通过JavaScript的prototype属性继承于BMap.Overlay
    CustomOverlay.prototype = new BMap.Overlay();


    CustomOverlay.prototype.initialize = function (map) {
        this._map = map;
        var div = this._div = document.createElement("div");
        div.className = "customOverlay";
        div.style.zIndex = BMap.Overlay.getZIndex(this._point.lat);
        div.style.background = "#ff0000";
        div.addEventListener("click", function () {
            alert(111);
        });
        map.getPanes().markerPane.appendChild(div);
        return div;

    }
    CustomOverlay.prototype.draw = function () {
        var map = this._map;
        var pixel = map.pointToOverlayPixel(this._point);
        this._div.style.left = pixel.x + "px";
        this._div.style.top = pixel.y + "px";
    }



    //百度地图API功能
    //加载第一张地图
    var map = new BMap.Map("allmap", { mapType: BMAP_NORMAL_MAP });             // 创建Map实例
    var point = new BMap.Point(116.404, 39.915);
    map.centerAndZoom(point, 11);
    map.enableScrollWheelZoom();                  //启用滚轮放大缩小
  
    var point1 = new BMap.Point(116.414, 39.915);
    var c1 = new CustomOverlay(point1);
    map.addOverlay(c1);

//    var marker = new BMap.Marker(point);
//    map.addOverlay(marker);
//    marker.addEventListener("click", function () {
//        alert("我是marker,我能触发click事件");
//    });
</script>

发现问题

用google浏览器的的手机模式进行调试,不会的请按f12


发现在手机模式下click事件并不会触发。

分析问题

我们禁用地图的拖拽功能

    map.disableDragging();
发现click事件可以触发了,为什么禁用了地图的拖拽功能就能触发click事件了呢?

我们可以大胆猜测,是地图的click事件阻止了覆盖物click事件的执行。

现在我们可以去验证一下,按f12找到覆盖物的元素节点(浏览器调试就不多说了,大家应该都知道)


既然事件被父元素阻止了,那么按理来说只要把元素添加到其他容器事件应该就能正常被触发了,我们可以来试试

我把元素拖动到如图所示的位置,发现果然可以正常地触发事件了,这表明我的猜测应该是正确的。

知道了问题之后就是要解决问题

我不知道大家有没有注意到我上面代码中注释掉的5行代码,这5行代码的作用的添加一个marker,并赋予click事件.

说到marker,他和覆盖物都是通过同一个函数map.addOverlay添加到地图中,在网页中添加的位置也相同,可是为什么marker的

click事件可以被触发,而overlay的click事件就不能被触发呢?

下面我们来看看marker与 overlay有什么不同

把代码添加到项目中,刷新网页找到marker的节点


我们发现marker有2个节点,我们首先找到的是上面那个节点,删除这个节点我们会发现marker还是在地图上,但是click事件却

不能被触发

删除下面那个节点,marker在地图上消失了,不过点击marker原来的位置,click还是会被触发

很明显百度地图在添加marker时把marker分为了2部分,一部分为网页上的显示,二部分是事件的触发。

解决问题

虽然没有分析出百度地图是如何实现click事件的,不过在研究的过程中也有了解决问题的思路

方法1

手机浏览器中最好用的方法还是touchstart,touchend,touchmove,虽然有时候不适用,但是我们可以用这三个事件组成
一个touchClick方法来模拟click事件
下面的代码是我从网上找到的方法
//给jquery添加touchClick方法
(function () {
    var defaults = {
        start: function (self, event) { },
        move: function (self, event) { },
        end: function (self, event) { }
    }
    $.fn.touchClick = function (opts) {
        if (typeof opts == "function") {
            opts = $.extend({}, defaults, { end: opts });
        } else {
            opts = $.extend({}, defaults, opts);
        }
        this.each(function () {
            var obj = $(this);
            obj.bind("touchstart", function (event) {
                obj.data("move", false);
                opts.start.call(this, event);
            }).bind("touchmove", function (event) {
                console.log(event.originalEvent.targetTouches.length);
                obj.data("move", true);
                opts.move.call(this, event);
            }).bind("touchend", function (event) {
                if (obj.data("move")) {
                    return;
                } else {
                    opts.end.call(this, event);
                }
                obj.data("move", false);
            });
        });
    };
})(jQuery);
    $(c1._div).touchClick(function () {
        alert("touchClick");
    });
这个方法需要jquery框架,还有一个缺点是在小米等手机中灵敏度不是很高

基于以上方法的缺点,我重新找了一个取巧办法

利用禁止地图拖拽能够触发click事件的特点
        c2._div.addEventListener("touchstart", function () {
            map2.disableDragging();  //禁用地图拖拽功能
        });

        c2._div.addEventListener("click", function () {
            alert("click");
        });
        c2._div.addEventListener("touchend", function () {
            map2.enableDragging();  //启用地图拖拽功能
        });
上面的代码乍一看可行,实际上是错误的,这个就要谈谈事件的执行顺序
在手机浏览器中鼠标点击的执行顺序是 touchstart->touchmove->touchend->click,这下就应该知道为什么上面的代码
是错误的了
我们删除toouchend事件,给地图添加touchmove事件
    map.addEventListener("touchmove", function () {
        map.enableDragging();
    });
这下就能正常执行click事件了
以下是全部的代码
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <style type="text/css">
        body, html
        {
            width: 100%;
            height: 100%;
            overflow: hidden;
            margin: 0;
            font-family: "微软雅黑";
        }
        #map1_container, #map2_container
        {
            width: 100%;
            height: 50%;
            float: left;
            overflow: hidden;
            margin: 0;
        }
        #allmap1
        {
            margin: 0 0 3px;
            height: 100%;
        }
        #allmap2
        {
            margin: 3px 0 0;
            height: 100%;
        }
        .customOverlay
        {
            background: #ff0000;
            width: 100px;
            height: 100px;
            position: absolute;
            cursor: pointer;
            -webkit-tap-highlight-color: rgba(0,0,0,0);
        }
    </style>
    <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=d48dRYg4j4K81puarHtLXBheW40bG1HW"></script>
    <title>2种地图</title>
    <script src="../../js/jquery.js" type="text/javascript"></script>
</head>
<body>
    <div id="map1_container">
        <div id="allmap1">
        </div>
    </div>
    <div id="map2_container">
        <div id="allmap2">
        </div>
    </div>
</body>
</html>
<script type="text/javascript">
    //给jquery添加touchClick方法
    (function () {
        var defaults = {
            start: function (self, event) { },
            move: function (self, event) { },
            end: function (self, event) { }
        }
        $.fn.touchClick = function (opts) {
            if (typeof opts == "function") {
                opts = $.extend({}, defaults, { end: opts });
            } else {
                opts = $.extend({}, defaults, opts);
            }
            this.each(function () {
                var obj = $(this);
                obj.bind("touchstart", function (event) {
                    obj.data("move", false);
                    opts.start.call(this, event);
                }).bind("touchmove", function (event) {
                    console.log(event.originalEvent.targetTouches.length);
                    obj.data("move", true);
                    opts.move.call(this, event);
                }).bind("touchend", function (event) {
                    if (obj.data("move")) {
                        return;
                    } else {
                        opts.end.call(this, event);
                    }
                    obj.data("move", false);
                });
            });
        };
    })(jQuery);


    /*
    *  自定义标注
    */
    var CustomOverlay = function (point, options) {
        this._point = point;
        this.opts = options;
    }
    // 通过JavaScript的prototype属性继承于BMap.Overlay
    CustomOverlay.prototype = new BMap.Overlay();




    CustomOverlay.prototype.initialize = function (map) {
        this._map = map;
        var div = this._div = document.createElement("div");
        div.className = "customOverlay";
        div.style.zIndex = BMap.Overlay.getZIndex(this._point.lat);
        div.style.background = "#ff0000";
        map.getPanes().markerPane.appendChild(div);
        return div;


    }
    CustomOverlay.prototype.draw = function () {
        var map = this._map;
        var pixel = map.pointToOverlayPixel(this._point);
        this._div.style.left = pixel.x + "px";
        this._div.style.top = pixel.y + "px";
    }
    //百度地图API功能
    //加载第一张地图
    var map1 = new BMap.Map("allmap1", { mapType: BMAP_NORMAL_MAP });             // 创建Map实例
    var point1 = new BMap.Point(116.404, 39.915);
    map1.centerAndZoom(point1, 11);
    map1.enableScrollWheelZoom();                  //启用滚轮放大缩小
    var c1 = new CustomOverlay(point1);
    map1.addOverlay(c1);
    $(c1._div).touchClick(function () {
        alert("touchClick");
    });
    var marker = new BMap.Marker(point1);
    map1.addOverlay(marker);
    marker.addEventListener("click", function () {
        alert("我是marker,我能触发click事件");
    });




    //加载第二张地图
    var map2 = new BMap.Map("allmap2", { mapType: BMAP_SATELLITE_MAP });            // 创建Map实例
    var point2 = new BMap.Point(116.404, 39.915);
    map2.centerAndZoom(point2, 11);
    map2.enableScrollWheelZoom();                  //启用滚轮放大缩小
    map2.addEventListener("touchmove", function () {
        map2.enableDragging();
    });
    var c2 = new CustomOverlay(point2);
    map2.addOverlay(c2);


    c2._div.addEventListener("touchstart", function () {
        map2.disableDragging();  //禁用地图拖拽功能
    });


    c2._div.addEventListener("click", function () {
        alert("click");
    });


</script>








评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值