Leaflet MarkerCluster stop auto re-clustering when zooming - leaflet

When you zoom in and out, the markerclusters automatically "re-cluster", as in it calculates clustering again.
Is there an option for to disable the auto re-cluster when the zoom is changed?

Depending on exactly what you are trying to achieve, you might be interested in Leaflet.MarkerCluster.Freezable subplugin:
When frozen / disabled, clusters will no longer split / merge on map zoom, but retain their status as if they were on the specified zoom level.
For example if you want the clusters to reflect the zoom 15 configuration:
var map = L.map("map"),
mcg = L.markerClusterGroup(options);
mcg.addLayers(arrayOfMarkers);
mcg.addTo(map);
mcg.freezeAtZoom(15);
Disclaimer: I am the author of that subplugin.

Is there an option for to disable the auto re-cluster when the zoom is changed?
No.
In Leaflet.MarkerCluster, the cluster depends on the value of the maxClusterRadius option, which is measured in screen pixels at the current zoom level.
I encourage you to have a look at the other Leaflet plugins for clustering, as some of them have clustering algorithms which do not depend on the zoom level.

Related

How do you get all features within a bounding box regardless of zoom?

Given a bound box like the below picture, how do you get all the features contained within, regardless of if they are visible or not.
I have tried to get all roads using
let features = map.querySourceFeatures('composite', {sourceLayer: 'road'})
But it only gives me roads that are visible if I am zoomed in.
I have also tried
let features = map.queryRenderedFeatures([tile_info.swPt, tile_info.nePt])
But again, it only gets features visible on the map based on zoom level.
I need all the features within the bounding box regardless of what you can see or zoom level
It is in the nature of vector tiles that you can not do what you want to do here. You can only query data which has been loaded into the browser, and the point of the vector tile architecture is to prevent that happening at lower zooms.
You could consider a server based approach like Tilequery.

Displayed zoom level vs tile zoom level: pixel density?

Tiles come with a zoom level, and depending on the area that is viewed, leaflet fills the display with tiles of a certain zoom level.
Currently, the number of pixels in the display and the number of pixels in a tile, are tightly bound together, if I understand correctly. Or actually, it is probably the html/css pixels, which are no longer device pixels.
I believe that these are actually two fundamentally different zoom parameters, especially when (mobile) devices have varying pixel densities (window.devicePixelRatio).
My question is: is it possible to control which zoom level of the tiles is shown, as a function of the zoom level that is displayed (geospatial distance vs screen distance)?
The reason I ask is that the level of detail is often different for different zoom levels. On some devices displaying tiles of higher detail might actually look good. Some map sources, like topographic maps from http://geoportail.gouv.fr even change the map style drastically between different levels. I want to play with the possibility of showing, say, zoom level 15 over a large physical area on a hdpi display, where leaflet would normally show zoom level 14 or 13.
I found that by modifying the option "tileSize", passed to the TileLayer constructor, choosing a value lower than the default 256, I get almost what I want. However: the positioning is way off. Is there a simple solution for this?
After some digging in the source code, I noticed, as IvanSanchez pointed out, that the functionality is present indeed.
detectRetina applies a zoom of 'one up', that is bumping the zoom by one and dividing the length of the sides of the tiles by two, if the device has a devicePixelRatio >= 2.
I want to apply an arbitrary offset at will. This can be done at once for a layer by initializing with the options
let zoomOffset = 2;
let options = {
"detectRetina" : false,
"zoomOffset" : zoomOffset,
"tileSize" : 256 / Math.pow(2, zoomOffset)
}
However, it's even neater to have the possibility to do this realtime while viewing, so I wrote this L.Control-plugin: Leaflet.Control.DetailLevel
I want to play with the possibility of showing, say, zoom level 15 over a large physical area on a hdpi display, where leaflet would normally show zoom level 14 or 13.
It seems that what you want is already implemented by the detectRetina option of L.TileLayers. Quoting the docs::
If true and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.

Limit leaflet cluster group expand depth

I am using cluster group. But how to limit cluster expand level. Suppose default cluster group loads with continent level then click. It expand to deeper level and when third time click on cluster group again it expand to country level. I want to fix three expand level of cluster group not below country level.
I tried freezeAtZoom() but it stops the cluster group from expand even from first level..
Your issue is still a little bit unclear.
Note first that when clicking on a cluster, it zooms to the extent of its child markers. This could represent a few zoom levels, depending on the actual child markers. It could even be directly the map's maximum zoom level, if all markers are really close one to each other. So there is no predefined target zoom level that the map will go to when you click, it all depends on the markers in that cluster.
Now if these markers do not change, and you can record the exact map's zoom level at which you want your clusters to no longer split apart on clicking, you have several ways to achieve that:
Define the map's maxZoom option to that zoom level, so that your users cannot go any deeper.
Add a map's "zoomend" event listener, so that if user goes deeper that your known zoom level, you freeze the cluster group to that recorded zoom. Remember that .freezeAtZoom(frozenZoom) can take an argument to specify at which zoom level the clusters should be frozen at, no matter the current zoom level.
Replace your individual markers by their equivalent cluster at your recorded zoom level ("country level"), maybe use Leaflet.markercluster singleMarkerMode option for styling, and iconCreateFunction option to override the counts and make them appear as if the clusters had many markers.

Is it possible to exclude pins at zoom levels

Created my first map at
http://rich.littlebigfoot.org.uk/test7.html
I am plotting walks on the coast path (the yellow) and will be adding more walks and more information. However at current zoom I would like to exclude all the pins and only show them at zoom level 11?
Thanks
Rich
If I understand correctly, you want to hide some layers (pins/markers and/or vectors/paths) at some low zoom levels (like [0 to 10]), and bring them back at high zoom levels (like 11 and above)?
You would probably be interested in attaching a callback on map "zoomend" event, so that callback can remove or add your layers to the map depending on the current map zoom level, when the latter changes.
For example:
map.on("zoomend", showOrHideLayers);
function showOrHideLayers() {
if (map.getZoom() <= 10) {
map.removeLayer(markers);
} else {
map.addLayer(markers);
}
}
showOrHideLayers();
Demo: http://jsfiddle.net/ve2huzxw/116/
EDIT:
If your objective is to avoid overlapping of pins (markers), you might also be interested in "Clustering" functionality.
Have a look at available Leaflet clustering plugins.
The most popular one is Leaflet.markercluster (demo).

Mapbox.js - Fallback tile image from lower zoom level, when missing in requested zoom level

I serve map png files from disk and I have tile pngs for whole city in zoom level 15. I have also tiles in zoom levels 16-18 but only for certain areas.
I would like to set up the tile Layer, so that when the user is in zoom level 18 the map will display scaled tiles from level 15 as a fallback.
I tried setting option maxNativeZoom, but didn't work for me.
Here is my code:
offlineLayer = L.mapbox.tileLayer(tileJSON, {
minZoom: 8,
maxZoom: 18,
maxNativeZoom: 15
});
map.addLayer(offlineLayer, 'Offline', 1);
Can I make it work, that way using some options or do I need to hack it some way? Or is there some example code for that?
Just to let people know that I wrote Leaflet.TileLayer.Fallback plugin some time ago to address this exact use case:
Replaces missing Tiles (404 error) by scaled lower zoom Tiles.
Demo page
In OP's situation, you would just specify the maxZoom Tile Layer option as usual, and whenever a tile is found missing at the current zoom level, the plugin will try to replace it by the "parent" tile at the previous zoom level (scaled and clipped appropriately so that it fits the missing tile), and so on until a tile is found or minZoom is reached.
L.tileLayer.fallback(urlTemplate, {
minZoom: 8,
maxZoom: 18
});
Disclaimer: I am the author of that plugin.
When you say that it didn't work for you, I'm guessing that what you're seeing with the code above is level 15 tiles for everywhere even when at zoom levels 16-18 in the areas where you have tiles at those levels? That's the expected behavior of maxNativeZoom. TileLayer creates all of the tiles for a given zoom level and map bounds and sets the "src" to a URL containing the current zoom level. If the current zoom level is greater than "maxNativeZoom" then the zoom level in the URL is set to "maxNativeZoom". For example, src="http://a.tile.openstreetmap.org/15/16368/10896.png" would be used for zoom levels 16-18 if "maxNativeZoom" is set to 15.
There is no logic in the code that checks to see if an image actually exists for that tile at that zoom level.
If your tiles are in a single data set then you could modify the code in TileLayer to check for a HTTP 404 return code for the generated URL and if one is received then create a new URL using "maxNativeZoom". If your tiles are in multiple data sets (i.e. one for zoom level 15 and less, and another for zoom levels 16-18) then I think you'd have to write a TileLayer that supports multiple data sets.