简体   繁体   中英

Match center of a Tile Layer with center of the Map on Leaflet

I am trying to make a Map of a Distribution Center using a flat image of the place. I need to be able to zoom in and out keeping a good quality of the image. So far I've been using Leaflet to draw the Map and MapTiler to create a tile schema that makes possible zooming without any quality loss and good performance.

I have everything set and working, but I need my Tile Layer center to match with the Map center. No matter what I do the Tile Layer top-left corner always starts at the (0,0) coordinate of the Map.

At zoom level 3, for example, my image is 1536x1280px, so the top-left corner should be at coordinate (-768,640) of the Map when talking about absolute pixel coordinates.

Here is my main script:

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

//mapHeight and mapWidth are the pixel dimensions of the flat image at max zoom level.
//In this case it's 6144x4608px. By default the tiles size is 256x256px.

var southWest = map.unproject([ 0, mapHeight], getMaxZoom());
var northEast = map.unproject([ mapWidth, 0 ], getMaxZoom());
var mapBounds = new L.LatLngBounds(southWest, northEast);

L.tileLayer('tile/{z}/{x}/{y}.png',{
    minZoom: 2,
    maxZoom: 5,
    noWrap:true,        
    bounds:mapBounds
}).addTo(map);  

I have messed with the center, setView and bounds, but no success in making the Tile Layer move.

The documentation of Leaflet can be found here http://leafletjs.com/reference.html

Please help me if you can. Thank you.

In Leaflet, tile coordinates are tightly bound to an internal mechanism - pixel coordinates.

For every zoom level, coordinates in LatLng get projected to the CRS coordinates (that's EPSG:4326→EPSG:3857 for earth maps and a vertical flip for L.CRS.Simple maps), then the CRS coordinate gets scaled by a factor dependant on the zoom level to give a pixel coordinate. Layers (tiles, markers, etc) are drawn using these pixel coordinates.

For "normal" tiles (of both GridLayer and TileLayer ), the {x} and {y} fields on the tile template URL are simply the pixel coordinate divided by the tile size. A 256px tile at pixel [0, 0] will have the tile coords [0, 0] , a tile at pixel [512, 256] will have [2, 1] and so on.

If you read the code for L.TileLayer.WMS , however, you'll notice that the tile URLs don't necessarily depend on the tile coordinates.

Back to your problem. You can overcome it by using the same strategy of L.TileLayer.WMS : overriding the getTileUrl method, with something like:

var t = L.tileLayer(…);

t.getTileUrl = function(coords) {
   var myZ = coords.z;
   var myX = coords.x + (8 * Math.pow(2, myZ - 3)); 
   var myY = coords.y + (6 * Math.pow(2, myZ - 3)); 

   return '/tile/' + myZ + '/' + myX + '/' + myY + '.png';
}

The code is simplistic (and I haven't bothered to make the math so that things fit where they should), but that should put you on the right track.


A different way to achieve the same would be to create a custom L.CRS based on L.CRS.Simple which applies a translation transformation to convert between LatLng s and CRS coordinates. If the code in src/geo/crs/CRS.Simple.js and src/geometry/Transformation.js in the Leaflet repo makes sense to you, I suggest you try this approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM