One possibility would be to use Leaflet's L.CRS.Simple
flat (Cartesian) CRS. Here one pixel corresponds to one map unit.
Let's say we want map units that correspond to original rasters map pixels (before it was cut to tiles): one map unit is one pixel on original raster. With tile layer at zoom level 0 whole map is within 256 x 256 pixels, so factor for desired map units is factor = 256 / maxWidthHeight
, where maxWidthHeight
is the bigger of raster width and height.
Leaflet will use this factor in all coordinate calculation if we change L.CRS.Simple
definition by extending it and changing transformation
method:
L.CRS.myCRS = L.extend({}, L.CRS.Simple, {
transformation: new L.Transformation(factor, 0, factor, 0)
});
Origin of our coordinate system wil be in top left corner, x going to the right and y down (because third parameter in transformation has positive value) and coordinates will be in the form [y, x]
(that's how L.CRS.Simple
is defined).
Let's see how this works on leaflet-rastercoords
plugin example https://commenthol.github.io/leaflet-rastercoords/example/index.html. Here original raster is 3831 x 3101 pixels, so factor would be 0.06682 = 256 / 3831
. Since actual map at zoom 0 is narrower that tile width (see below), if we want to have lower right corner at [3101, 3831]
, the correct factor is 0.062495.
This is the whole code:
var width = 3831;
var height = 3101;
var factor = 0.062495;
L.CRS.myCRS = L.extend({}, L.CRS.Simple, {
transformation: new L.Transformation(factor, 0, factor, 0)
});
var map = L.map('map', {
crs: L.CRS.myCRS
}).setView([height/2, width/2], 2);
L.tileLayer('https://commenthol.github.io/leaflet-rastercoords/example/tiles/{z}/{x}/{y}.png', {
minZoom: 0,
maxZoom: 5,
noWrap: true
}).addTo(map);
map.on('click', function (event) {
var coords = event.latlng;
var marker = L.marker(coords).addTo(map);
marker.bindPopup('[' + Math.floor(coords.lat) + ',' + Math.floor(coords.lng) + ']').openPopup();
});
On map click marker is created and popup displayed with marker coordinates.