DEV Community

Rafael Lage
Rafael Lage

Posted on

Using react-leaflet to generate one tiled layer

The problem: Leaflet does not support single tile layer.

(This was posted in 2017, on medium)

Which means that if you need to render some dynamic cluster, generated by geoserver, like this:leaflet-1

Leaflet will, instead, show something like this:leaflet-2

Which is messed up. Fortunately, we (me and Arlindo Pereira, at MPRJ) got a workaround using ImageOverlay element from Leaflet, which is pretty simple, but it took a lot of time to discover.

React-leaflet is a lib that exposes components to work with leaflet. So it exposes react components like Map, TileLayer, WMSTileLayer, and so on. It also exposes ImageOverlay. To get this to work, you need to use ImageOverlay component like this:

<ImageOverlay
  bounds={imageBounds}
  url={imageURL}
  transparent={true}
/>
Enter fullscreen mode Exit fullscreen mode

Where imageBounds needs to be a Leaflet Bounds object, which should be the bounds for the current visible portion of the map, like this:

{
 “_southWest”:
 {
 “lat”:-24.27701247166408,
 ”lng”:-46.65893554687501}
 }
 ”_northEast”:
 {
 “lat”:-21.927759064052037,
 ”lng”:-37.86987304687501
 }
}
Enter fullscreen mode Exit fullscreen mode

The imageURL parameter is the URL to the service that will generate the image and should be like this:

let imageURL = `${ENDPOINT}?
SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=
image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=
${layer.layerName}&SRS=EPSG%3A4326&WIDTH=
${clientWidth}&HEIGHT=
${clientHeight}&BBOX=
${imageBounds._southWest.lng}%2C
${imageBounds._southWest.lat}%2C
${imageBounds._northEast.lng}%2C
${imageBounds._northEast.lat}`
Enter fullscreen mode Exit fullscreen mode

This is a WMS call. The main things you should note are the Height, Width and Bbox attributes. The height and width need to be in pixels and related to the size of the map in your app, so to speak. Our map fits the html document, so we got it like this:

let clientHeight = document.body.clientHeight
let clientWidth = document.body.clientWidth
Enter fullscreen mode Exit fullscreen mode

And the Bbox is the same coordinate as mentioned before.
You can see how it was before:

mprj-1

And how it is now:

mprj-2

Or here, live: http://apps.mprj.mp.br/sistema/inloco/
Here to see the code: https://github.com/MinisterioPublicoRJ/inLoco-2.0

InLoco is aGeographic Information System (GIS) used by Ministério Público do Estado do Rio de Janeiro to show social, institutional and administrative data, made with React and Leaflet, interacting with a public GeoServer backend. You are welcome to send you PR =)

Top comments (0)