leaflet - manually cluster markers - leaflet

I need to manually cluster/uncluster few markers on the map (not automatically by zoom)
is there a way to tell Leaflet.markercluster which markers to cluster manually and not automatically by zoom.
I tried manipulating the L.markerClusterGroup layer internal cluster._gridClusters and cluster._gridUnclustered which holds an array of all the zooms and markers/clusters in each.
but changing the objects seems to do nothing and not represented on map.
a solution example would be:
selectedMarkers = [marker1,marker2,marker3];
map.cluster(selectedMarkers);
map.uncluster(selectedMarkers);
please help.

Related

Update leaflet baselayer properties with GoogleMutant

I have a google layer (baselayer) GoogleMutant and want to update its options. I try to
map.remove(google.layer)
//update the POI visibility
google.layer.options.styles.forEach(i=>i.stylers[0].visibility = "off")
map.addLayer(google.layer)
this updates the layer options but the Points of interest are still on the map. Is there any way to update the options and apply them to the baselayer?
Thanks
Here is an example with google mutant https://jsfiddle.net/benderlio/2m4c01w6/10/
There is a button "remove POI", and I want to remove all poi from current layer with leaflet API
Leaflet doesn't work changing settings on the fly. You have to remove the whole object and create a substitute.
Like if you need to change a layer, you have to remove it like:
roadMutant.removeFrom(map); // or
map.removeLayer(roadMutant);
And then create and add the new one:
roadMutant.addTo(map);
I created a fiddle to help the change based on yours. It still have bugs and somewhere to grow, but it's a base...

Leaflet markercluster group and layer control not working

I'm trying to add clustering and layer control to filter markers on my map. After reading older posts on this issue, the code that was marked as the right answer looks like this. However, no matter how I change it, it does not work on my map.
var parent= new L.MarkerClusterGroup().addTo(map);
var overlay={}
overlay["Markers A"]=L.featureGroup.subGroup(parent,aPoints).addTo(map);
overlay["Markers B"]=L.featureGroup.subGroup(parent,bPoints).addTo(map);
control = L.control.layers(null, overlay, {collapsed: false });
control.addTo(map);
What am I doing wrong?
The issue that I was having was that L.featureGroup.subGroup takes in an array of markers as it's second parameters therefore, aPoints needed to be [aPoints].

Refresh marker clusters after GeoJSON layer has changed

I am setting up a GeoJSON layer and on top of it a MarkerCluster layer
this.itemLayer = L.geoJson(items, layerOptions)
this.clusterLayer = L.markerClusterGroup()
this.clusterLayer.addLayer(this.itemLayer)
this.clusterLayer.addTo(this.map)
Upon update I am doing:
this.itemLayer.clearLayers()
this.itemLayer.addData(newItems)
this.clusterLayer.refreshClusters(this.itemLayer)
But the clusters do not appear, nor do the items in the itemLayer
Solution
this.itemLayer.clearLayers()
this.itemLayer.addData(this.props.items)
this.clusterLayer.clearLayers()
this.clusterLayer.addLayer(this.itemLayer)
Leaflet.markercluster does not keep track of Layer Groups (like your this.itemLayer GeoJSON layer group) unfortunately. When passed a group to clusterLayer.addLayer(), MCG will extract all individual (i.e. non-group) layers from that group, and forget any reference to the group.
See also Leaflet.markercluster issue #647.
Therefore when clearing your group with this.itemLayer.clearLayers(), it effectively removes all children from this.itemLayer, but this.clusterLayer is unaffected.
Similarly when adding data to this.itemLayer, that group creates new child layers, but MCG is unaffected.
Then when calling this.clusterLayer.refreshClusters(this.itemLayer), none of the child layers of this.itemLayer are part of this.clusterLayer, so it ends up with unexpected effect (maybe just doing nothing special).
If you want to change the clustered layers, make sure to remove them from MCG (e.g. simply do this.clusterLayer.clearLayers()), then add back the new layers into it. You could also remove the current MCG and build a new one.

No setBounds function for Leaflet imageOverlay

I'm reading an imageOverlay URL from an ArcGIS webserver that uses the leaflet getBound() coordinates as part of the URL (we have large maps that are filtered for the current window 'extent'). Apologies for not including the actual path (I'm working with sensitive client data). Eg:
http://myarcgiswebserver.com/MapServer/export/dpi=96&format=png32&bbox=27.119750976562504%2C-31.194007509998823%2C32.39044189453126%2C-29.692824739380754&size=1719%2C434
[bbox] = current imageBounds
When dragging my map the imageOverlay url is updated correctly but my leaflet window is no longer aligned to the imageBound values that were set when first adding the imageOverlay which results in a skewed output (this is my assumption):
The only workaround is to remove the existing imageOverlay and add a new one (which ruins the user experience as the map disappears then reappears each time the window is dragged or zoomed).
Am i approaching this problem incorrectly or would the introduction of a function to update the current imageBounds resolve this? Perhaps not a new function but the expansion of setUrl with additional parameters...?
Many thanks for any feedback...
As #ghybs pointed out, your use case might be better served by using the WMS
interface of your ArcGIS server.
Anyway, you say
The only workaround is to remove the existing imageOverlay and add a new one (which ruins the user experience as the map disappears then reappears each time the window is dragged or zoomed).
Well, that glitch is due to you probably doing something like:
Remove old overlay
Add new overlay
Wait until the image is received from the network
Wait one frame so the new overlay is shown
and instead you should be doing something like:
Add new overlay
Wait until the image is received from the network
Remove old overlay
Wait one frame so the new overlay is shown
The problem is just the async wait and the possible race conditions there, but should be easy to hack together, e.g.:
var activeOverlay = null;
var overlayInRequest = null;
map.on('moveend zoomend', {
// If we are already requesting a new overlay, ignore it.
// This might need some additional debouncing logic to prevent
// lots of concurrent requests
if (overlayInRequest) {
overlayInRequest.off('load', showOverlay);
}
overlayInRequest = L.imageOverlay( computeUrl( map.getBounds() ), myOverlayOptions );
overlayInRequest.on('load', showOverlay);
});
function showOverlay(ev) {
activeOverlay.remove();
activeOverlay = overlayInRequest;
activeOverlay.addTo(map);
overlayInRequest = undefined;
}
If you use an ImageOverlay but change its url dynamically, with a new image that reflects a new bounding box, then indeed that is the reason for the behaviour you describe: you display an image that has been generated using a new bbox, but positioned in the initial bbox, since the image overlay remains at the same geographical position on the map.
Instead, it sounds to me that you should use a TileLayer.WMS.
It would automatically manage the bounding box update for you. You may need to find the correct options to fit your service provider required URL syntax, though.
Example: http://playground-leaflet.rhcloud.com/yel/1/edit?html,output

Using leaflet.js, how do I iterate through markers in a cluster?

Se we have a map and at a certain zoom level we start clustering the markers.
Now I want to be able to delete certain markers. I can delete the markers that don't participate in a cluster but the markers in a cluster do not get deleted because the code doesn't iterate through them.
I'd post code but it's all over the place and quite specific.
I can do the following;
$.each(MAP._layers, function (i, layer) {
if (layer.feature) {
var marker = LIGHTWEIGHT_BUILDING_MAPPING[layer.feature.id];
MAP.removeLayer(marker);
}
});
And all the visible markers are removed but not the ones within a cluster. Any thoughts?
You can't iterate though markers in a map or a cluster.
Create an array where you push the markers when you create them.
Iterate through your array
When you have to remove a marker, use
if(cluster.hasLayer(marker) cluster.removeLayer(marker);
if(map.hasLayer(marker) map.removeLayer(marker);
// remove marker from array (easier with a jQuery Array)