1
votes

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?

2

2 Answers

1
votes

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.

1
votes

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