Reputation: 1507
I have a map with Custom HTML Markers and a MarkerClusterer, the clusterer works fine, but I want to filter markers by radius to a location, I am able to get the markers inside the given radius, however I am not able to hide the markers outside the given radius and show only the markers inside that radius from the MarkerClusterer.
I am defining my custom marker like this:
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;
};
I am using MarkerClustererPlus and using setIgnoreHidden(true)
will hide all the markers including the marker that is supposed to be visible.
I have noticed that marker.getVisible()
, which is used by the MC+ when using setIgnoreHidden(true)
, returns false for the markers outside the given radius as expected, but undefined for the markers inside a cluster.
I think that it is because when a cluster is formed, the elements inside it get removed, not just hidden, hence setting them to null.
CustomMarker.prototype.remove = function ()
{
if (this.div)
{
this.div.parentNode.removeChild(this.div);
this.div = null;
}
};
See Example JS Fiddle.
https://jsfiddle.net/enriqg9/az21h1b5/
Upvotes: 0
Views: 3170
Reputation: 161334
If you want the marker to be visible, you need to set its map
property:
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());
}
code snippet:
/* ==========================================================================
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>
Upvotes: 3