Is there any way we can calculate the scale ratio using L.CRS.scale?

For example, if I execute the following code L.CRS.scale(this._map.getZoom()), the pixel coordinates value for a particular zoom would be 1763487.599042158. So, my question is how to find what ratio (i.e. 1:500, 1:1000 etc) is and how to calculate it from the return value of scale?

The table below shows the resolution (meters per pixel) and scale of the zoom levels within the EPSG:27700 tile matrix set. The resolution is calculated at a DPI of 96.

enter image description here

1 Answer 1


Is there any way we can calculate the scale ratio using L.CRS.scale?

Using L.CRS.scale for that kind of calculation is cumbersome and most probably unreliable in the end. The result of L.CRS.scale() has to be multiplied by a CRS-dependant constant (the world bounds according to that CRS) in order to make the numbers meaningful, which IMO leads to confusion. As explained elsewhere, the implementation of L.CRS is geared towards quickly displaying things on a screen, and not towards an abstract GIS understanding of CRSs.

Instead, I suggest doing as L.Control.Scale does: calculate the distance in meters between two points at known places in the screen, with a known distance in pixels between them.

The relevant code from L.Control.Scale I'm referring to is

    var y = map.getSize().y / 2;
    var maxMeters = map.distance(
        map.containerPointToLatLng([0, y]),
        map.containerPointToLatLng([this.options.maxWidth, y]));

That calculates the distance in map meters between two points in a horizontal line in the middle of the map, measuring this.options.maxWidth CSS pixels wide.

So if you're assuming 96 DPI, that means (after a tiny bit of math) a centimeter is 38 pixels. So if you replace this.options.maxWidth with 38 in the aforementioned code, you'll end up with the amount of map meters that correspond to a screen centimeter. Deriving a scale factor from those numbers is trivial.

This approach has the advantage of not needing any constants from the CRS definition, since the distance() function does the heavy lifting for you.

This approach has the disadvantage of a varying scale factor for the same zoom level (which might in fact be desireable if the projection distorts lengths). This can be worked around by replacing the implementation of L.CRS.distance with a cartesian distance of projected coordinates implementation.

  • What is then the meaning/use of L.CRS.scale method for the end user? For example, L.CRS.EPSG3857.scale(0) gives result of 256, while for EPSG:27700 defined with proj4, result is 0.000007559039. I couldn't find connection between those two values. The second value is actually reverse of resolution for zoom 0 for EPSG:27700 , which is 132291.93.
    – TomazicM
    Commented Feb 11, 2022 at 23:11
  • @TomazicM Its meaning depends. It's the size (height,width) of the world in pixels for the given zoom level for EPSG:3857, the height of the world and half its width for EPSG:4326, and the size in pixels of one map unit in L.CRS.Simple. I dunno about its meaning when using proj4leaflet. It was certainly not meant to be used by end users. Commented Feb 12, 2022 at 0:17

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.