Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding an extra zoom levels in Leaflet Maps

Im using leaflet to create a photo map, with my own tiles, which works as expected.

Im trying to work out how I can prevent the zoom from following this Quadtree type pattern:

  • Zoom Level 0 - Entire map width = 256px;
  • Zoom Level 1 - Entire map width = 512px;
  • Zoom Level 2 - Entire map width = 1024px;
  • And so on...

I would like to be able to zoom in say increments of 25% or 100px.

An example of 100px increments:

  • Zoom Level 0 - Entire map width = 200px;
  • Zoom Level 1 - Entire map width = 300px;
  • Zoom Level 2 - Entire map width = 400px;
  • And so on...

Question: What is the logic for doing this? If it is at all possible?


My reason for wanting to do this is so that my photo map (which doesnt wrap like a normal map) can be more responsive and fit the users screen size nicely.

I made a demonstration of my issue which can be seen here

like image 828
Blowsie Avatar asked Oct 31 '12 08:10

Blowsie


People also ask

How do you increase zoom in leaflet?

A leaflet map has several ways to control the zoom level shown, but the most obvious one is setZoom() . For example, map. setZoom(0); will set the zoom level of map to 0 .

How many zoom levels are there in Google Maps?

Zoom Level+Maximum/Minimum Zoom. Google Maps has an integer 'zoom level' which is the resolution of the current view. Zoom levels are between 0 (the entire world can be seen on one map) and 21+. You can also set the minimum and maximum values for the zoom parameter.

What is map zoom level?

A zoom level or scale is a number that defines how large or small the contents of a map appear in a map view . Scale is a ratio between measurements on a map view and measurements in the real-world.

Are leaflet maps free?

Leaflet is open source and free. However the examples on leaflet site use Mapbox to render map. Mapbox is more expensive than Google map (Mapbox pricing).


1 Answers

The short answer is that you can only show zoom levels for which you have pre-rendered tiles. Leaflet won't create intermediary zoom levels for you.

The long answer is that in order to use do this, you need to define your own CRS scale method and pass it to your map, for example:

L.CRS.CustomZoom = L.extend({}, L.CRS.Simple, {
    scale: function (zoom) {
        // This method should return the tile grid size
        // (which is always square) for a specific zoom
        // We want 0 = 200px = 2 tiles @ 100x100px,
        // 1 = 300px = 3 tiles @ 100x100px, etc.
        // Ie.: (200 + zoom*100)/100 => 2 + zoom

        return 2 + zoom;
    }
});

var map = L.map('map', { crs: L.CRS.CustomZoom }).setView([0, 0], 0);

In this example, I've extended L.CRS.Simple, but you can of course extend any CRS from the API you'd like, or even create your own from scratch.

Using a zoom factor which results in a map pixel size that is not a multiple of your tilesize, means your right/bottom edge tiles will only be partially filled with map data. This can be fixed by making the non-map part of such tiles 100% transparent (or same the colour as your background).

However, it is, in my opinion, a much better idea to set the tilesize to match the lowest common denominator, in this case 100px. Remember to reflect this by using the tileSize option in your tile layer. And, of course, you will need to re-render your image into 100x100 pixels tiles instead of the 256x256 tiles you are using currently.

One caveat, the current version of LeafletJS (0.5) has a bug that prevents a custom scale() method from working, due to the TileLayer class being hardcoded to use power-of-2 zoom scaling. However, the change you need to do is minor and hopefully this will be addressed in a future release of Leaflet. Simply change TileLayer._getWrapTileNum() from:

_getWrapTileNum: function () {
    // TODO refactor, limit is not valid for non-standard projections
    return Math.pow(2, this._getZoomForUrl());
},

To:

_getWrapTileNum: function () {
    return this._map.options.crs.scale(this._getZoomForUrl());
},
like image 139
ttherkelsen Avatar answered Dec 09 '22 23:12

ttherkelsen