Google Maps has a nice feature called Marker Clusterer which lets you to apply grid-based clustering to a collection of markers.
Marker Clusterer counts every marker as one, it sums up the number of markers in the grid. Differently, I want to assign a weight to every marker and sum up these weights in the cluster. Is it possible with Google Maps API? Do you know any other javascript library which provides a similar feature?
It's not as complicated as it seems.
The markerclusterer-library provides the option to override the calculator-function(this is the function that will build the cluster-icons).
Store the weight as a property of the markers, e.g.:
new google.maps.Marker({position:new google.maps.LatLng(1,2),weight:8});
The calculator-function may look like this:
var calc=function(markers, numStyles) {
var weight=0;
for(var i=0;i<markers.length;++i){
weight+=markers[i].weight;
}
return {
text: weight,
index: Math.min(String(weight).length, numStyles)
};
}
To apply this custom function:
initialize the clusterer without markers:
var markerCluster = new MarkerClusterer(map);
set the function
markerCluster.setCalculator(calc);
add the markers:
markerCluster.addMarkers(markers);
Demo: http://jsfiddle.net/doktormolle/H4EJu/
The pitfall: the calculator-function will have to iterate over all markers(by default it doesn't, it only calculates based on the length of the markers-array). This will affect the performance of the MarkerClusterer, especially when you have a lot of markers.
Related
I'm using superclsuter for clustering markers in react native map, what I want is to get all children from a cluster no matter what level of nesting a cluster may have.
to explain the situation a little better, a cluster can have markers and other clusters as children, I need to flatten the child clusters to get markers inside them.
cluster
marker
cluster(3 markers)
// this should return the 4 markers, the top-level marker, and markers within the child cluster
I know it is late for an answer, but this solution is for google map using google-map-react package.
First on initializing the map options, add maxZoom and minZoom. maxZoom must be equal to supercluster max-zoom
On cluster rendering use this code:
if(isCluster){
if(zoom>=15){
return (
//Create MultiMarker similar to the marker below but different infowindow style to display list of places and display text
<MultiMarker
key={`cluster-${cluster.id}`}
lat={latitude}
lng={longitude}
text={`${pointCount} Listing`}
places={supercluster.getChildren(cluster.id)}
>
</MultiMarker>
)
}else{
return ClusterMarker;
}
}
return Normal or Custom marker;
For cluster reference: https://www.leighhalliday.com/google-maps-clustering
I'm working on a leaflet map where many markers are shown with prunecluster, and I need to get the list of clusters that are currently shown in the map.
I have initialized the clusters with
var pruneCluster = new PruneClusterForLeaflet(150, 70);
The only array of the cluster I'm seeing in the developers tools and in the code is pruneCluster.Cluster._clusters. Actually it is a mostly exact representation of the clusters shown in the map, but, sometimes, the length of that array is different from the number of clusters that are shown in the map. I.e., that array doesn't represent the situation I have in the map.
What array should I use?
That pruneCluster.Cluster._clusters contains all the clusters it calculated, but since you can pan and zoom the map, the visible clusters can be a subset of it.
You can iterate over the clusters and test if they are visible. Like this:
// Get the bounds of the map visible in the browser
// 'map' is your Leaflet map
var boundsOfView = map.getBounds();
// Iterate all prune clusters
var allClusters = pruneCluster.Cluster._clusters;
var clustersInView = [], clusterBounds;
for (var i = 0; i < allClusters.length; i += 1) {
clusterBounds = allClusters[i].bounds;
// Is this cluster visible? (within the visible bounds?)
if (boundsOfView.intersects([[clusterBounds.minLat, clusterBounds.minLng], [clusterBounds.maxLat, clusterBounds.maxLng]])) {
// Yes, visible, so store it
clustersInView.push(allClusters[i]);
}
}
// Now you have all your visible clusters in 'clustersInView'
It is using these Leaflet methods:
getBounds() to get the bounds of the visible part of the map
intersects() to test if the boundaries of a cluster intersect the bounds of the map, i.e. visible or not
And of PruneCluster:
bounds (line 83 in the source code), which contains the min/max coordinates of a cluster
Hope it helps!
I have a Google Map object available on my window object like so:
var map = window.site.map.el;
That Map also also has a bunch of markers placed on it, I'd like to hide a Marker on that Map where the marker's place_id property is equal to "123" for example.
However I don't see a function I can call on the Map class that will return me an array of all markers placed on the map that I can then loop through and hide depending on the marker's place_id.
Google maps does not provide a way to get all Markers, you need to do it yourself
while adding marker to the map keep it in array
var myMarkers = [];
....
for(...) {
var marker = new google.maps.Marker({...});
myMarkers.push(marker);
}
Than you can hide any marker, just by setting map to null
myMarker[i].setMap(null);
Or bring it back
myMarker[i].setMap(map);
Let's say I have the following objects:
var map = new google.maps.Map(...)
var marker = new google.maps.Marker(...);
I can add marker to map with:
marker.setMap(map);
If the marker already exists on the map, and I call marker.setMap(map) again, does the API actually redraw the marker? Or does it know the marker already exists on the map, so it doesn't take any further actions?
I am listening for events and need to either add or remove markers from the map when those events occur. I'm wondering if I can simply keep calling setMap(map) even if the marker already exists without performance suffering significantly, or do I need to be smarter and not call setMap in the first place if the marker is already on the map.
If you don't know the answer, do you have any idea how I could figure this out?
If the marker already exists on the map, and I call marker.setMap(map)
again, does the API actually redraw the marker? Or does it know the
marker already exists on the map, so it doesn't take any further
actions?
The setMap function work on the visibility of the marker... assing to the marker in which map object this marker must be place/visibile..
If you set marker.setMap(null) you don't destroy the marker simply is not more showed in the "map".
when you manage event on marker you can use setMap(null) for make the marker invisible.. if you have previuosly stored the marker object in some var..eg
var store_marker = marker;
you can simply turn it on again doing
store_marke.setMap(map);
You can use array for manage collection of markers
Is there any way to remove the markers that the directions put on the map? I have 4 locations that show on the map. A green arrow where the user is and 3 locations marked A, B, C. If I click on one it routes between the user's location and the marker. The problem is that google adds a new A & B marker to the map as the start and end of the directions. Now I have a couple A and B markers on the map and it's pretty confusing.
Thanks
In the DirectionsRendererOptions set suppressMarkers to true
This is an old post, but I ran on the same issue. I have map with my own markers, I would select few of them and starting point, then I would show directions with markers A, B, C... The problem was how to remove directions and show my markers again.
Here is what worked for me to remove direction paths with markers (A, B, C, etc..).
directionsDisplay.setMap(null);
directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setMap(map);
RefreshMarkers(); //your function to draw your markers
directionDisplay is declared globally. It's API v3.
Not sure if this is helpful or not. When you create a new GDirection and supply it with a map object, it will automatically draw the polyline to the map as soon as the direction is loaded. This also automatically adds the markers at the start and end of the journey.
I've noticed, however, that if you don't supply the map object initially and instead use the the 'load' event listener to manually add the polyline to the map, you get the line but not the markers.
//Don't supply a map to GDirections()
var direction = new GDirections();
//Make sure {getPolyline:true} is given to the load function
direction.load("here to there", {getPolyline:true});
GEvent.addListener(direction,
"load",
function(){ map.addOverlay(direction.getPolyline()); }
);
This might be easier than finding and removing the markers, especially if you're using the 'load' event listener anyway.
For each marker you want to remove, do
marker.setMap(null);
http://code.google.com/apis/maps/documentation/v3/overlays.html#Markers
Hit menu then layers and on the lower left press clear map. That should clear out everything on the map.
Normally you'd be able to simply do marker.setMap(null), but because the Directions call automatically places the A & B markers on the map, you do not have direct access to them and therefore cannot remove them in this way.