【问题标题】:Google Maps Custom HTML Marker and MarkerClustererPlus谷歌地图自定义 HTML 标记和 MarkerClustererPlus
【发布时间】:2016-05-20 06:38:54
【问题描述】:

我有一个带有自定义 HTML 标记和 MarkerClusterer 的地图,群集器工作正常,但我想按半径过滤标记到某个位置,我能够获取给定半径内的标记,但是我无法隐藏给定半径之外的标记,并仅从 MarkerClusterer 显示该半径内的标记。

我正在这样定义我的自定义标记:

function CustomMarker(latlng, map, args)
{
    this.latlng = latlng;
    this.args = args;
    this.setMap(map);
    this.map = map;
}

CustomMarker.prototype = new google.maps.OverlayView();

CustomMarker.prototype.draw = function ()
{
    var self = this;

    if (!this.div)
    {
        var div = document.createElement('div');

        div.className = 'marker';
        div.style.position = 'absolute';
        div.style.cursor = 'pointer';

        var span = document.createElement('span');
        span.innerHTML = 'X';

        div.appendChild(span);

        var panes = this.getPanes();
        panes.overlayImage.appendChild(div);

        this.div = div;
    }

    var point = this.getProjection().fromLatLngToDivPixel(this.latlng);

    if (point)
    {
        this.div.style.left = (point.x - 20) + 'px';
        this.div.style.top = (point.y - 20) + 'px';
    }

    google.maps.event.addDomListener(this.div, "click", function (event)
    {
        google.maps.event.trigger(self, "click");
    });
};

CustomMarker.prototype.remove = function ()
{
    if (this.div)
    {
        this.div.parentNode.removeChild(this.div);
        this.div = null;
    }
};

CustomMarker.prototype.getPosition = function ()
{
    return this.latlng;
};

CustomMarker.prototype.getDraggable = function ()
{
    return false;
};

CustomMarker.prototype.setVisible = function (visible)
{
    if (this.div)
    {
        if (visible)
        {
            this.div.style.display = 'table';
            this.visible = true;
        }
        else
        {
            this.div.style.display = 'none';
            this.visible = false;
        }
    }
};

CustomMarker.prototype.getVisible = function ()
{
    return this.visible;
};

我正在使用 MarkerClusterPlus 并且使用 setIgnoreHidden(true) 将隐藏所有标记,包括应该可见的标记。

我注意到marker.getVisible()(在使用setIgnoreHidden(true) 时由MC+ 使用)对于给定半径之外的标记返回false,如预期的那样,但对于集群内的标记返回未定义。

我认为这是因为当一个集群形成时,它里面的元素会被移除,而不仅仅是隐藏,因此将它们设置为 null。

CustomMarker.prototype.remove = function ()
{
    if (this.div)
    {
        this.div.parentNode.removeChild(this.div);
        this.div = null;
    }
};

参见示例 JS Fiddle。

https://jsfiddle.net/enriqg9/az21h1b5/

【问题讨论】:

    标签: javascript google-maps google-maps-api-3


    【解决方案1】:

    如果你想让标记可见,你需要设置它的map属性:

    for (var n = 0; n < this.markers.length; n++) {
      var marker = this.markers[n];
      var distance = google.maps.geometry.spherical.computeDistanceBetween(marker.getPosition(), location) / 1609;
      if (distance > radius) {
        // 4 Markers over 10 mile radius should be hidden
        marker.setVisible(false);
      } else {
        // Only 1 marker should be kept visible
        marker.setMap(this.map);
        visibleMarkers.push(marker);
      }
      console.log(marker.getVisible());
    }
    

    proof of concept fiddle

    代码 sn-p:

    /* ==========================================================================
     Google Maps
     ========================================================================== */
    var map = {
      'map': '',
      'markers': [],
      'lat': 31.862491,
      'lng': -106.3650707,
      'createMap': function() {
        this.map = new google.maps.Map(document.getElementById('map'), {
          center: {
            lat: this.lat,
            lng: this.lng
          },
          zoom: 6,
          maxZoom: 18,
          scrollwheel: false,
          disableDefaultUI: true,
          zoomControl: true
        });
        this.createMarkers($object);
      },
      'createMarkers': function(response) {
        var self = this;
        var infoWindow = new google.maps.InfoWindow({
          content: 'Loading'
        });
        var bounds = new google.maps.LatLngBounds();
        for (var n = 0; n < response.length; n++) {
          var el = response[n];
          var lat = parseFloat(el.lat);
          var lng = parseFloat(el.lng);
          var latLng = new google.maps.LatLng(lat, lng);
          var marker = new CustomMarker(latLng, this.map, {
            title: el.title
          });
          this.markers.push(marker);
          bounds.extend(marker.getPosition());
          google.maps.event.addListener(marker, 'click', function() {
            infoWindow.setContent('<b>' + this.args.title + '</b>');
            infoWindow.open(self.map, this);
            self.map.panTo(this.getPosition());
            self.map.setZoom(14);
          });
        }
        // New markerClustererPlus
        this.mc = new MarkerClusterer(this.map, this.markers, {imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'});
      },
      'filter': function(location) {
        var bounds = new google.maps.LatLngBounds();
        var visibleMarkers = [];
        // For testing purposes
        var radius = 10;
        var location = new google.maps.LatLng(this.lat, this.lng);
        // Hide Markers not inside given radius
        for (var n = 0; n < this.markers.length; n++) {
          var marker = this.markers[n];
          var distance = google.maps.geometry.spherical.computeDistanceBetween(marker.getPosition(), location) / 1609;
          if (distance > radius) {
            // 4 Markers over 10 mile radius should be hidden
            marker.setVisible(false);
          } else {
            // Only 1 marker should be kept visible
            marker.setMap(this.map);
            visibleMarkers.push(marker);
          }
          console.log(marker.getVisible());
        }
        for (var n = 0; n < visibleMarkers.length; n++) {
          bounds.extend(visibleMarkers[n].getPosition());
        }
        this.mc.setIgnoreHidden(true);
        this.map.fitBounds(bounds);
      }
    };
    var btn = document.getElementById('filter');
    btn.addEventListener('click', function() {
      map.filter();
    });
    var $object = [{
      "lat": -20.823485,
      "lng": 23.24177,
      "title": "Explicabo voluptates voluptatibus quas sed laborum minus quia."
    }, {
      "lat": -27.503418,
      "lng": 32.594705,
      "title": "Repellat ea reiciendis quae dolores sit facilis ut."
    }, {
      "lat": -53.468797,
      "lng": -125.400102,
      "title": "Perspiciatis voluptates consectetur nulla inventore illo debitis delectus alias."
    }, {
      "lat": "31.80666009999999",
      "lng": "-106.50467950000001",
      "title": "321 Mesa St"
    }, {
      "lat": "31.831369",
      "lng": "-106.55140799999998",
      "title": "123 Main St"
    }];
    /* ==========================================================================
     Custom Maker
     ========================================================================== */
    function CustomMarker(latlng, map, args) {
      this.latlng = latlng;
      this.args = args;
      this.setMap(map);
      this.map = map;
    }
    CustomMarker.prototype = new google.maps.OverlayView();
    CustomMarker.prototype.draw = function() {
      var self = this;
      if (!this.div) {
        var div = document.createElement('div');
        div.className = 'marker';
        div.style.position = 'absolute';
        div.style.cursor = 'pointer';
        var span = document.createElement('span');
        span.innerHTML = 'X';
        div.appendChild(span);
        var panes = this.getPanes();
        panes.overlayImage.appendChild(div);
        this.div = div;
      }
      var point = this.getProjection().fromLatLngToDivPixel(this.latlng);
      if (point) {
        this.div.style.left = (point.x - 20) + 'px';
        this.div.style.top = (point.y - 20) + 'px';
      }
      google.maps.event.addDomListener(this.div, "click", function(event) {
        google.maps.event.trigger(self, "click");
      });
    };
    CustomMarker.prototype.remove = function() {
      if (this.div) {
        this.div.parentNode.removeChild(this.div);
        this.div = null;
      }
    };
    CustomMarker.prototype.getPosition = function() {
      return this.latlng;
    };
    CustomMarker.prototype.getDraggable = function() {
      return false;
    };
    CustomMarker.prototype.setVisible = function(visible) {
      if (this.div) {
        if (visible) {
          this.div.style.display = 'table';
          this.visible = true;
        } else {
          this.div.style.display = 'none';
          this.visible = false;
        }
      }
    };
    CustomMarker.prototype.getVisible = function() {
      return this.visible;
    };
    map.createMap();
    #map {
      height: 400px;
    }
    .marker {
      display: table;
      width: 40px;
      height: 40px;
      background-color: #353535;
      border: 3px solid #FF9000;
      border-radius: 50px;
      color: #fff;
      font-size: 1em;
      font-weight: bold;
      text-align: center;
    }
    .marker span {
      display: table-cell;
      vertical-align: middle;
    }
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry"></script>
    <script src="https://cdn.jsdelivr.net/gh/googlemaps/v3-utility-library@master/markerclustererplus/src/markerclusterer.js"></script>
    <div id="map"></div>
    
    <button id="filter">Filter</button>
    
    <p>
      Clicking the Filter button should display 1 marker, bounds get properly set but marker is not visible.
    </p>
    
    <p>
      If you click on the cluster before clicking the filter button, the markers inside it get visible, and clicking filter will work as expected, as there are no markers inside a cluster.
    </p>

    【讨论】:

      猜你喜欢
      • 2015-05-25
      • 2013-08-21
      • 1970-01-01
      • 2011-11-05
      • 2015-10-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多