Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A layer for single-tile WMS layers. Displays a layer as a big picture, updates it on pan and zoom. This is a hack, made for an internal project; still waiting for https://github.com/Leaflet/Leaflet/issues/558 to be solved nicely. Example: L.singleTile('http://irs.gis-lab.info/').setParams({layers: 'landsat'}).addTo(map); (won't work, because tha…
/*
* L.SingleTile uses L.ImageOverlay to display a single-tile WMS layer.
* url parameter must accept WMS-style width, height and bbox.
*/
L.SingleTile = L.ImageOverlay.extend({
defaultWmsParams: {
service: 'WMS',
request: 'GetMap',
version: '1.1.1',
layers: '',
styles: '',
format: 'image/jpeg',
transparent: false
},
initialize: function( url, options ) {
this.wmsParams = L.extend({}, this.defaultWmsParams);
L.ImageOverlay.prototype.initialize.call(this, url, null, options);
},
setParams: function (params) {
L.extend(this.wmsParams, params);
return this;
},
redraw: function () {
this._updateImageUrl();
},
onAdd: function (map) {
var projectionKey = parseFloat(this.wmsParams.version) >= 1.3 ? 'crs' : 'srs';
// this.wmsParams[projectionKey] = 'EPSG:4326'; // this is incorrect!
this.wmsParams[projectionKey] = map.options.crs.code;
L.ImageOverlay.prototype.onAdd.call(this, map);
map.on('moveend', this._updateImageUrl, this);
},
onRemove: function (map) {
map.on('moveend', this._updateImageUrl, this);
L.ImageOverlay.prototype.onRemove.call(this, map);
},
// Copypasted from L.ImageOverlay (dirty hack)
_initImage: function () {
this._image = L.DomUtil.create('img', 'leaflet-image-layer');
if (this._map.options.zoomAnimation && L.Browser.any3d) {
L.DomUtil.addClass(this._image, 'leaflet-zoom-animated');
} else {
L.DomUtil.addClass(this._image, 'leaflet-zoom-hide');
}
this._updateOpacity();
this._bounds = this._map.getBounds();
//TODO createImage util method to remove duplication
L.extend(this._image, {
galleryimg: 'no',
onselectstart: L.Util.falseFn,
onmousemove: L.Util.falseFn,
onload: L.bind(this._onImageLoad, this),
src: this._constructUrl()
});
},
_onImageLoad: function () {
this._bounds = this._map.getBounds();
this._reset();
this.fire('load');
},
_updateImageUrl: function () {
this._image.src = this._constructUrl();
},
_constructUrl: function () {
var size = this._map.getSize();
var b = this._map.getBounds();
return this._url + L.Util.getParamString(this.wmsParams, this._url) + "&width=" + size.x + "&height=" + size.y + "&bbox=" + b.toBBoxString();
}
});
L.singleTile = function (url, options) {
return new L.SingleTile(url, options);
};
@homme

This comment has been minimized.

Copy link

@homme homme commented Jun 17, 2013

Very useful! I added the following function to enable the layer to be re-drawn when WMS parameters are updated:

    redraw: function () {
        this._updateImageUrl();
    }
@Zverik

This comment has been minimized.

Copy link
Owner Author

@Zverik Zverik commented Jun 17, 2013

Thanks, added this function to the gist.

@HansWapenaar

This comment has been minimized.

Copy link

@HansWapenaar HansWapenaar commented Sep 12, 2017

Hi,
Tried this layer to get png files from mapserver/mapscript/asp.net handler - application.
Works good!

In my application I switch from a geojson layer ( L.GeoJSON.AJAX) to a singletile layer when there are large quantities of polygons and switch back to geojson when there are small quantities of polygons.
Found a problem when the singletile-layer is removed from the map. But checking on (this._map != null) in the constructURL function did the trick.
I also added a random parameter to make sure that a redraw is forced when there is no zooming or panning. This was necessary for changing a theme triggered by a button. With no url changes the map from the cache is shown.
Thanks, Hans

	_constructUrl: function () {
	    if (this._map != null) {
	        var size = this._map.getSize();
	        var b = this._map.getBounds();
	        var valrandom = {
	            item: Math.random(),
	            toString: function () {
	                return this.item;
	            }
	        };
	        return this._url + L.Util.getParamString(this.wmsParams, this._url) + "&width=" + size.x + "&height=" + size.y + "&test=" + valrandom + "&bbox=" + b.toBBoxString();
	    }
	}
@mercelsantos

This comment has been minimized.

Copy link

@mercelsantos mercelsantos commented May 16, 2018

This is an awesome script and very useful. I've tried to use it to plot a canvas image in leaflet maps. But I had no success. First I created a canvas image then I converted it to URL string using the following command my_canvas.toDataURL(). Finally, I used L.SingleTile to display my canvas image in leaflet but I did not work. Do you have any idea why it does not work with canvas image?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment