3

I have two sets of tiles. One for zoom level 10 and one for zoom level 14. However, I want to be able to see tiles on my map at zoom levels 9 through 15. For the nonexistent sets of tiles I want to use the tiles from either level 10 or 14 and scale them accordingly. E. g. at the zoom level 9, 11 and 12 I want to have the tiles from the level 10 displayed, but scaled by factor 0.5, 2 and 4 respectively and at the zoom level 13 and 15 I want to have the tiles from the level 14 displayed and scaled by factor 0.5 and 2. I can achieve this for the levels 9 and 15 using the "maxNativeZoom" and "minNativeZoom" options, but how to do this with the other zoom levels?

In Open Layers, which I am using now I can solve this by specifying the "server resolutions" and "client resolutions" options. Now I want to try Leaflet - mostly because of better handling of overlays. That means I want to find a solution that works with overlays, like markers.

I've been looking at the setTransform function, which probably scales the tiles in the case of max/minNativeZoom, but my knowledge of Javascript and HTML is limited and I couldn't figure out how to use it.

Here's my scratch:

<html>
    <head>
        <title>Leaflet map</title>
        <link rel="stylesheet" href="leaflet.css" />
        <script src="leaflet.js"></script>
    </head>
    <body>
        <div id="mapid" style="width:100%; height:100%;"></div> 
        <script>
var mymap = L.map('mapid').setView([46.5, 8], 10);
L.tileLayer('tiles/{z}/{x}/{y}.png',{maxNativeZoom: 14, maxZoom: 15, minNativeZoom: 10, minZoom: 9}).addTo(mymap);
        </script>
    </body>
</html>

2 Answers 2

3

One possible solution would be to use Leaflet.LimitZoom plugin. It makes possible to specify native zoom levels and allowed zoom levels. Missing zooms are interpolated from existing native zooms.

Allowed zoom levels are declared with zooms option when creating map. Native zoom levels are declared with nativeZooms option when creating layer.

In your case it would look something like:

var mymap = L.map('mapid', {
  zooms: [9, 10, 11 ,12, 13, 14, 15],
  minZoom: 9,
  maxZoom: 15
}).setView([46.5, 8], 10);

L.tileLayer('tiles/{z}/{x}/{y}.png',{
  nativeZooms: [10, 14]
}).addTo(mymap);

What's missing in plugin is some kind of control over interpolation: which native zoom level is used when during interpolation, but this could probably be easly overcome by modifying/extending plugin.

5
  • This doesn't seem to have any effect on my map. May be that the last update was for Leaflet 1.0.2 and I am using 1.5.1?
    – SofaGuy
    Commented Aug 24, 2019 at 17:11
  • It works for me with leatest Leaflet. Did you include both Leaflet.LimitZoom.js and Leaflet.ContinuousZoom.js libraries?
    – TomazicM
    Commented Aug 24, 2019 at 17:18
  • Yes. This is my code <html> <head> <title>Leaflet map</title> <link rel="stylesheet" href="leaflet.css" /> <script src="leaflet.js"></script> <script src="Leaflet.LimitZoom.js"></script> <script src="Leaflet.ContinuousZoom.js"></script> </head> <body> <div id="mapid" style="width:100%; height:100%;"></div> <script> var mymap = L.map('mapid', { zooms: [9, 10, 11 ,12, 13, 14, 15], minZoom: 9, maxZoom: 15 }).setView([46.5, 8], 10); L.tileLayer('tiles/{z}/{x}/{y}.png',{ nativeZooms: [10, 14] }).addTo(mymap); </script> </body> </html>
    – SofaGuy
    Commented Aug 24, 2019 at 19:20
  • Here is JSFiddle that works with latest Leaflet: jsfiddle.net/TomazicM/ed4rfabx/2. If you inspect in browser with network debugger, you'll see that only tiles from zoom 10 and 14 are fetched.
    – TomazicM
    Commented Aug 25, 2019 at 8:13
  • Well it turned out I downloaded the html page with the link to .js files, instead of the .js-es themselves. I always get confused with downloading of code from Github. However, now it works "like a charm". The only drawback is - as you mentioned - that it's deciding itself which levels to use where. But I can live with that. Thanks!
    – SofaGuy
    Commented Aug 25, 2019 at 10:25
1

I can achieve this for the levels 9 and 15 using the "maxNativeZoom" and "minNativeZoom" options, but how to do this with the other zoom levels?

Yuo can do that with max/minNativeZoom as well!

E. g. at the zoom level 9, 11 and 12 I want to have the tiles from the level 10 displayed, but scaled by factor 0.5, 2 and 4 respectively [...]

So in that case, define a tilelayer with both maxNativeZoom = 10 and minNativeZoom = 10, like:

L.tileLayer("tilesForZoom10/{z}/{x}/{y}.png", {
    maxNativeZoom: 10,
    minNativeZoom: 10,
    minZoom: 9,
    maxZoom: 12,
});

[...] and at the zoom level 13 and 15 I want to have the tiles from the level 14

Same thing:

L.tileLayer("tilesForZoom14/{z}/{x}/{y}.png", {
    maxNativeZoom: 14,
    minNativeZoom: 14,
    minZoom: 13,
    maxZoom: 15,
});

This will give you two separate tilelayers, which you can manage as one by creating a L.LayerGroup (for use in a L.Control.Layers etc), e.g.:

var tiles10 = L.tileLayer("tilesForZoom10/{z}/{x}/{y}.png",
    { maxNativeZoom: 10, minNativeZoom: 10, minZoom: 9, maxZoom: 12 });
var tiles14 = L.tileLayer("tilesForZoom10/{z}/{x}/{y}.png",
    { maxNativeZoom: 14, minNativeZoom: 14, minZoom: 13, maxZoom: 15 });

var tiles = L.layerGroup([tiles10, tiles14]);
1
  • Thanks for the answer. I've tried the approach you suggested, but it looks like the webpage always loads the tiles from both layers for any zoom level. For example when I zoom out to level 10, it still loads all the tiles from level 14. After the loading is finished, the 14-tiles are removed, however it is causing an unnecessary (and quite long) delay. Also when I reload the page, it lands on zoom 12, even if I specify 14 in L.map(). To me it seems like the minZoom and maxZoom options are ignored.
    – SofaGuy
    Commented Aug 24, 2019 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.