5

I would like to add a raster wms layer to Mapbox GL but in similar way as OpenLayers single tiles example

Mapbox example https://docs.mapbox.com/mapbox-gl-js/example/wms/ use the 256px tile's size declared in code:

map.on('load', function () {
map.addSource('wms-test-source', {
'type': 'raster',
// use the tiles option to specify a WMS tile source URL
// https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/
'tiles': [
'https://img.nj.gov/imagerywms/Natural2015?bbox={bbox-epsg-3857}&format=image/png&service=WMS&version=1.1.1&request=GetMap&srs=EPSG:3857&transparent=TRUE&width=256&height=256&layers=Natural2015'
],
'tileSize': 256
});
map.addLayer(
{
'id': 'wms-test-layer',
'type': 'raster',
'source': 'wms-test-source',
'paint': {}
},
'aeroway-line'
);
});

On the other hand, OpenLayers set the single tile size automatically depending on container's size (full screen in my case):

new OpenLayers.Layer.WMS(
    "Single Tile", 
    "http://vmap0.tiles.osgeo.org/wms/vmap0",
    {layers: "basic"}, 
    {singleTile: true, ratio: 1}
)

Is possible to make something similar using Mapbox?

3

1 Answer 1

7

You can find below the same code as in the comment to make only single WMS calls (useful to avoid repeated labels). I've made some refactoring. You should also be aware that you need to consume a WMS server that is able to return single WMS calls (some third party servers have size limitations making them unable to display large WMS images)

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Add a WMS Single source</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox-gl-js/v1.11.0/mapbox-gl.js"></script>
<script src="https://unpkg.com/@mapbox/[email protected]/sphericalmercator.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.11.0/mapbox-gl.css" rel="stylesheet" />
    <style>
    body {
      margin: 0;
      padding: 0;
    }

    #map {
      position: absolute;
      top: 0;
      bottom: 0;
      width: 100%;
    }
    </style>
</head>
<body>
<div id="map"></div>
<script>
    function getExtentCoordinatesFromBounds(bounds) {
      return [
        bounds.getNorthWest().toArray(),
        bounds.getNorthEast().toArray(),
        bounds.getSouthEast().toArray(),
        bounds.getSouthWest().toArray()
      ];
    }
    function wmsExtent130FromBounds(bounds) {
      var sm = new SphericalMercator({
        size: 256
      });
      return [
        ...sm.forward(bounds.getSouthWest().toArray()),
        ...sm.forward(bounds.getNorthEast().toArray())
      ];
    }
    function addSingleWms(map, baseUrl) {
      return function() {
        var myCanvas = map.getCanvas();
        var myBounds = map.getBounds();
        var imageCoordinates = getExtentCoordinatesFromBounds(myBounds);
        var imageExtent3857 = wmsExtent130FromBounds(myBounds);
        if (map.getSource(sourceName) && map.getLayer(wmsLayerName)) {
            map.removeLayer(wmsLayerName);
            map.removeSource(sourceName);
        }
        var urlWms = `${baseUrl}?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image/png&TRANSPARENT=true&LAYERS=topp:states&CRS=EPSG:3857&STYLES=&FORMAT_OPTIONS=dpi:180&WIDTH=${myCanvas.width / window.devicePixelRatio}&HEIGHT=${myCanvas.height / window.devicePixelRatio}&BBOX=${imageExtent3857.join(',')}`;
        map.addSource(sourceName, {
          'type': 'image',
          'url': urlWms,
          'coordinates': imageCoordinates
        });
        map.addLayer({
          'id': wmsLayerName,
          'type': 'raster',
          'source': sourceName,
          'paint': {}
        });
      }
    }
    var map = new mapboxgl.Map({
      container: 'map',
      style: {
        "version": 8,
        "sources": {
          "raster-tiles": {
            "type": "raster",
            "tiles": ["a", "b", "c"].map(subdomain => "https://" + subdomain + ".tile.openstreetmap.org/{z}/{x}/{y}.png"),
            "tileSize": 256
          }
        },
        "layers": [{
          "id": "simple-tiles",
          "type": "raster",
          "source": "raster-tiles",
          "minzoom": 0,
          "maxzoom": 20
        }]
      },
      zoom: 8,
      center: [-74.5447, 40.6892]
    });

    var sourceName = 'wms-test-source';
    var wmsLayerName = 'wms-test-layer';
    var baseUrl = 'https://ahocevar.com/geoserver/wms';
    map.on('load', addSingleWms(map, baseUrl));
    map.on('moveend', addSingleWms(map, baseUrl));
</script>
 
</body>
</html>

The same code demo, visible in the browser https://gist.githack.com/ThomasG77/0feccc76e01bdbfd98b7f628c1c4e6f0/raw/def838975465efcf45884af95960cad3185c343d/mapbox-gl-js-wms-single-call.html to see the code in action.

1
  • I added demo example from comment, so it's all together in one place.
    – TomazicM
    May 21, 2021 at 19:16

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.