Limit map zooms to integer zoom level after initial fractional zoom in Leaflet?

I have a map that defaults to a fractional zoom level for a particular reason. (I need to keep it this way if at all possible.)

However, whenever the user zooms in or out by any means, I want the map to zoom to an integer zoom level, but without zooming twice (e.g., leaflet zooms to a fractional level and then my code zooms a second time to an integer level).

I have set zoomDelta and zoomSnap to 1 after setting the map view, but doing this has not achieved what I want: zooming in or out still just changes the zoom level by 1, so the result is still a fractional value.

(To clarify, let's say default zoom is 2.25. If the first zoom is a zoom out, it should result in 1, because that's 2.25 rounded to 2 and then minus 1. If the first zoom is a zoom in, it should result in 3, which is 2.25 rounded to 2 then plus 1. Any further zooming would just be +/- 1 as usual because we would be starting from an integer.)

``````        map = L.map('map', {
maxBoundsViscosity: 1.0,
zoomControl: false
}).setView([defLat, defLon], 2.25);

L.setOptions(map, { zoomDelta: 1, zoomSnap: 1 });

//coded this way because the variable is needed elsewhere
let zoomControls = L.control.zoom({ position: 'bottomright' }).addTo(map);
``````

I have tried listening for 'zoomstart', 'zoom', and 'zoomend', then putting a setZoom() in these listeners, but the setZoom() causes the double-zoom that I'm trying to avoid.

``````    map.on('zoomend', function (e) {
let level = map.getZoom();
let levelAsInteger = Math.round(level);

if (level !== levelAsInteger) {
map.setZoom(levelAsInteger);
}
});
``````

So is there some way to ensure the map always zooms to an integer zoom level even though it starts at a fractional zoom level?

Note that the solution has to work for all zooming - whether by mousewheel or zoom buttons on the map - so I can't just customize the zoom button onclicks.

• Before starting with this one, what happened/is happening with your previous question gis.stackexchange.com/questions/465873/…. It has answer that works, proven with JSFiddle example. Commented Sep 1, 2023 at 8:06
• I have posted an update on the previous question. I very much hope the issues behind the two questions are not related and that this one will be an easy fix. Commented Sep 1, 2023 at 13:23

Solution to allow initial fractional zoom is to initially set map `zoomSnap` option to a value that allows desired fractional zoom. After initial `setView` this option is then set to 1 to prevent fractional zooms.

Code could then look like this:

``````map = L.map('map', {
zoomSnap: 0.01,
maxBoundsViscosity: 1.0,
zoomControl: false
}).setView([defLat, defLon], 2.25);

L.setOptions(map, {
zoomSnap: 1
});
``````
• I used your solution in a jsfiddle and I can see that it works. However, for some reason, it does not work on my map. In both cases, I put a listener on zoomend and console logged map.getZoom(). The jsfiddle is logging an integer and my map is not. In my map, I also console logged map.options and there is nothing unexpected in there, and yet somehow there is something in my code that is causing this not to work. Are you aware of anything that might stop/prevent the zoomSnap from working as expected? Commented Sep 5, 2023 at 15:26
• Without you being able to reproduce your problem in a simple JSFiddle, it's impossible to say why it does not work for you. This is the second time that my solution did not work for you, so there must be something going on in your code that changes it's behavior. Commented Sep 5, 2023 at 15:43
• Definitely. There is a lot of code within the same file that I did not write, and although I'm sure it wasn't intended to override default maps behaviour, that must be what it's doing. (That's also why I'm struggling to find it: it's a "needle in a haystack" situation to find code - written by someone else - that is interfering with zoom and spiderfy but isn't intended to affect them in any way.) This page will be refactored in the next couple of months, and if that reveals the issue, I will post an update on both my questions so future viewers can see what the problem was. Commented Sep 5, 2023 at 18:24