So my basemap is a world Mercator projection and in wfs format and I'm trying to put a WMS overlay in a different projection over it? Leaflet's API didn't give me much info on changing the epsg so is it even possible?

  • Just request the WMS in the SRS of your base map - GeoServer will handle the reprojection for you.
    – Ian Turton
    Commented Nov 27, 2012 at 8:31
  • @iant can you provide an example of how to do this with Leaflet? I understand in GeoServer's WMS we just append something like &srsName=epsg:3857 to the URL, but how can we pass this into Leaflet?
    – modulitos
    Commented Dec 16, 2014 at 0:42

3 Answers 3


Leaflet supports PseudoMercator projection out-of-the-box (EPSG:3857). You can force Leaflet to use a few other projections listed here in the documentation. Don't worry, I found leaflet's API documentation kind of 'meh'. Documentation by programmers...

World Mercator is supported with a easy to use method, lucky you.


You just place that anywhere in the global scope of your script and it should set your projection for you map.

Additionally, there is a plugin for leaflet that can allow you to use more 'uncommon' projections. Proj4Leaflet

Note: It doesn't appear that Leaflet will tranform your layer into another projection like ArcGIS or QGIS but will just take the data at face value and render it that way. You will need to serve your data in the projection that your tell Leaflet to use.

  • Thx, I'm actually taking over a leaflet related project and I was able to find that bit of code, but the issue was that it was part of a minified library called leaf-custom.js and so the code is just one long horizontal line that won't wrap so I have to disseminate it. Commented Nov 27, 2012 at 14:39
  • Oh so the actual map implementation is an external, minified library? If so, try just adding the projection line in the script body like you would if building the map yourself. I think it would behave just the same.
    – RomaH
    Commented Nov 27, 2012 at 14:44
  • Not exactly, certain configurations are being hard-coded within the external minified library, but there is a map implementation file and a few other files to render the views all part of a namespace that draws from the minified library so I have to figure out where to make modifications. Commented Nov 27, 2012 at 14:55

In Leaflet 0.7 you can assign a different CRS to each WMS Layer by using its csr option.

var myLayer = L.tileLayer.wms(...);
myLayer.options.crs = L.CRS.EPSG4326;
  • I have same requirement. The point is that is it possible to add wms layer with crs different than the map's crs? Commented Mar 22, 2018 at 12:55

This is my attempt to display the layer in projection 3395. I determine the offset between the projections 3857 and 3395 in pxs _getReprojectOffset() and redefine private functions _getTilePos(), _getTiledPixelBounds

var map = L.map('map', {
    crs: L.CRS.EPSG3857,
    center: [51, 55],
    zoom: 12

L.TileLayer.EPSG3395 = L.TileLayer.extend({     
    _getReprojectOffset: function(latLng, zoom) {
        var mapProjectPoint = this._map.options.crs.latLngToPoint(latLng, zoom);
        var lyrProjectPoint = L.CRS.EPSG3395.latLngToPoint(latLng, zoom);   
        return lyrProjectPoint.subtract(mapProjectPoint);
    _getTilePos: function (coords) {        
        var tileBounds = this._tileCoordsToBounds(coords);          
        var reprojOffset = this._getReprojectOffset(tileBounds._northEast, coords.z);
        return coords.scaleBy(this.getTileSize()).subtract(this._level.origin).subtract(reprojOffset);

    _getTiledPixelBounds: function (center) {
        var map = this._map,
            mapZoom = map._animatingZoom ? Math.max(map._animateToZoom, map.getZoom()) : map.getZoom(),
            scale = map.getZoomScale(mapZoom, this._tileZoom),
            pixelCenter = map.project(center, this._tileZoom).floor(),
            halfSize = map.getSize().divideBy(scale * 2);
        var reprojOffset = this._getReprojectOffset(center, this._tileZoom).floor();
        return new L.Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize).add(reprojOffset));

L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=yuor_token_key', {
    maxZoom: 18,
    attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, ' +
        'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
    id: 'mapbox/streets-v11',
    tileSize: 512,
    zoomOffset: -1

L.tileLayer.epsg3395 = function(templateUrl, options) {
    return new L.TileLayer.EPSG3395(templateUrl, options);


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.