zoukankan      html  css  js  c++  java
  • [Google Maps API 3]Marker从Clusterer中分离及Marker置于Cluster上一层的解决办法

    在Google Maps API的使用中,经常用到Clusterer来避免过密的Marker显示。但仔细看一下Clusterer的设置参数中并没有直接将某些Marker除外的方法,那遇到这样的需求,怎么做呢?以下是我从StackoverFlow上获得的解答,也是实践下来最佳的方法:

    // Create marker clusterer
    // map: google.maps.Map Object
    // markerArray: [google.maps.Marker Object1, google.maps.Marker Object2 ...]
    var clusterer = new MarkerClusterer(map, markerArray, {
        maxZoom: 15,
        gridSize: 40
    });
    // Separate the map pin from the cluster
    // specialMarker: google.maps.Marker Object
    clusterer.removeMarker(specialMarker);
    specialMarker.setMap(map);

    思路很简单,就是用Clusterer对象提供的方法将Marker从中移除,然后用Marker对象的setMap方法使其回到map上。

    然后你就会发现另外有一个问题出现了。这个被分离出来的Marker总是在Clusterer的下面一层。客户很不爽。看到有人说要靠建立自定义的OverlayView来把Marker画在Clusterer的上面一层,不过也没看到有具体的解决办法,于是我硬着头皮上了。对谷歌文档半熟的人来说,看到他们列出来的一堆东西很头疼,往往不知道怎么下手。

    首先要知道Google Map上总共分了7个层,具体可以参考API文档OverlayView及Panes的部分,说明还是很详细的。

    我们可以知道直接用Marker对象画出来的Map pin是在OverlayLayer这一层内,好像是第3层,而Cluster位于其上的OverlayImage这一层内。各层HTML按序从上到下排列,CSS是用position:absolute定位,zIndex定先后层级。

    那么从这可以看出,其实如果只要显示Marker在Clusterer上方通过改变zIndex是很容易做到的。问题是,这么做因为原来的层级被搞乱导致一些事件,比如Clusterer的点击事件不能触发。

    然后我用了个假的Marker画在比较高层的Pane上以假乱真。如下:

    var maxZoom = 15;
    var markerClusterer = new MarkerClusterer(map, markerArray, {
        maxZoom: maxZoom,
        gridSize: 40
    });
    // separate the map pin from the cluster
    if (specialMarker) {
        markerClusterer.removeMarker(this.centerMarker);
        //specialMarker.setMap(this.map);
        // Make the map pins over the clusters
        if ($(map.getDiv()).find('.special-marker').length < 1) {
            // Create the OverlayView structor
            var overlay = function (marker) {
                this.pos = marker ? marker.getPosition() : new google.maps.LatLng();
                this.marker = marker;
            };
            var markerOverlay;
    // Extend google.maps.OverlayView Class // You must add onAdd, onRemove, Draw function to its prototype overlay.prototype = new google.maps.OverlayView(); overlay.prototype.onAdd = function () { var pane = this.getPanes().floatPane; var marker = this.marker; // Add fake marker and attach click event to it $('<div class="special-marker"></div>').appendTo($(pane)).on('click', function () { google.maps.event.trigger(marker, 'click'); }); };
    overlay.prototype.onRemove = function () { // You can leave this function empty // It's only triggered when you call markerOverlay.setMap(null) };
    overlay.prototype.draw = function () { // Calculate the position of the marker and put it on the map // Hide the fake one when the true marker shows var projection = this.getProjection(); var position = projection.fromLatLngToDivPixel(this.pos); var $pane = $(this.getPanes().floatPane); $('.special-marker', $pane).css({ left: position.x - 11, top: position.y - 41, position: "absolute" }).toggle(map.getZoom() <= maxZoom); };
    markerOverlay = new overlay(specialMarker); markerOverlay.setMap(map); } }

    这里我先创建了一个自定义层,插入到第7层Pane的floatPane内最后。然后我用了个跟真Marker一模一样的图标作为这个层的背景,尺寸22px*41px,根据真Marker的位置计算出来在Map上的位置,用CSS绝对定位到指定位置。并且,很重要的是,把真Marker上的click事件绑定到这个假Marker上,因为点击Marker会显示InfoWindow。最后,为了避免真假Marker同时显示在Map上,加了一层判断。

    实际上,以假乱真可以说是多余的,你可以直接画自己的Marker,作为真Marker来用,当然这也有一定的风险。

  • 相关阅读:
    SQLSERVER查询所有数据库名,表名,和字段名
    SQL通过拆分某字段中的内容来实现与对应表连接查询
    [SPOJ]CIRU 圆并
    有关反演和GCD
    docker部署 jenkins
    mongoDB学习记录(二)
    docker动态修改容器限制
    ORACLE数据库误操作DELETE并且提交数据库之后如何恢复被删除的数据
    用8个命令调试Kubernetes集群
    db2服务器linux的cache过高原因
  • 原文地址:https://www.cnblogs.com/jennieji/p/separate_marker_from_clusterer_and_show_marker_at_top.html
Copyright © 2011-2022 走看看