Updating cluster icon after updating children - leaflet

In this contrived example, I'm showing temperature measurements on a map, and using the markercluster plugin to cluster markers that get too close. I'm using the iconCreateFunction of the cluster group to generate an icon that reflects the average temperature of the children in the group.
My problem is that I want to update the temperatures of the markers over time, and have the cluster icons update to reflect these changes. Is there any way to trigger the iconCreateFunction on all the clusters after an update?

I found this solution which is a bit hacky, but does work:
if you have your marker group
var markers = new L.MarkerClusterGroup(...);
then you can force the clusters to update their icons by something like
for (var cluster in markers._featureGroup._layers) {
markers._featureGroup._layers[cluster]._updateIcon && markers._featureGroup._layers[cluster]._updateIcon();
}

The "official" solution seems to be to re-add the marker to the clustergroup, as found here: https://github.com/Leaflet/Leaflet.markercluster/issues/287
this can be done simply with:
var markers = new L.MarkerClusterGroup(...);
...
markers.removeLayer(marker);
markers.addLayer(marker);

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].

leaflet - manually cluster markers

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.

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)