Created
June 12, 2013 09:50
-
-
Save fnicollet/5764080 to your computer and use it in GitHub Desktop.
Single tile WMS layer for Leaflet. Kind of hacked on top of ImageOverlay, a new image is requested when the viewport is changed. Supports reprojection through proj4-leaflet There are actually 2 images (_image and _imageSwap) because if you use the _image from ImageOverlay, and set his "src" attribute to the new WMS bbox, your layer will disappea…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
goog.provide('L.SingleTileWMSLayer'); | |
goog.require('L.Map'); | |
L.SingleTileWMSLayer = L.ImageOverlay.extend({ | |
defaultWmsParams: { | |
service: 'WMS', | |
request: 'GetMap', | |
version: '1.1.1', | |
layers: '', | |
styles: '', | |
format: 'image/jpeg', | |
transparent: false | |
}, | |
initialize: function (url, options) { // (String, Object) | |
this._url = url; | |
if (url.indexOf("{s}") != -1){ | |
this.options.subdomains = options.subdomains = '1234'; | |
} | |
var wmsParams = L.extend({}, this.defaultWmsParams); | |
/* | |
if (options.detectRetina && L.Browser.retina) { | |
wmsParams.width = wmsParams.height = this.options.tileSize * 2; | |
} else { | |
wmsParams.width = wmsParams.height = this.options.tileSize; | |
} | |
*/ | |
for (var i in options) { | |
if (!this.options.hasOwnProperty(i)) { | |
wmsParams[i] = options[i]; | |
} | |
} | |
this.wmsParams = wmsParams; | |
// = imageSwap et affichée now | |
this._isSwap = false; | |
this._imageSwap = null; | |
L.setOptions(this, options); | |
}, | |
onAdd: function (map) { | |
this._map = map; | |
var projectionKey = parseFloat(this.wmsParams.version) >= 1.3 ? 'crs' : 'srs'; | |
this.wmsParams[projectionKey] = map.options.crs.code; | |
// | |
this._bounds = map.getBounds(); | |
// pan | |
map.on('moveend', this._onViewReset, this); | |
// hide on zoom | |
if (map.options.zoomAnimation && L.Browser.any3d) { | |
map.on('zoomanim', this._onZoomAnim, this); | |
} | |
// request a first image on add | |
this._onViewReset(); | |
// override | |
//L.ImageOverlay.prototype.onAdd.call(this, map); | |
}, | |
onRemove: function (map) { | |
// super() | |
L.ImageOverlay.prototype.onRemove.call(this, map); | |
// add | |
if (this._imageSwap){ | |
map.getPanes().overlayPane.removeChild(this._imageSwap); | |
} | |
map.off('moveend', this._onViewReset, this); | |
map.off('zoomanim', this._onZoomAnim, this); | |
}, | |
_onViewReset: function () { | |
this._futureBounds = this._map.getBounds(); | |
var map = this._map; | |
var crs = map.options.crs; | |
var nwLatLng = this._futureBounds.getNorthWest(); | |
var seLatLng = this._futureBounds.getSouthEast(); | |
var topLeft = this._map.latLngToLayerPoint(nwLatLng); | |
var bottomRight = this._map.latLngToLayerPoint(seLatLng); | |
var size = bottomRight.subtract(topLeft); | |
var nw = crs.project(nwLatLng), | |
se = crs.project(seLatLng); | |
var bbox = [nw.x, se.y, se.x, nw.y].join(','); | |
var url = this._url; | |
this.wmsParams.width = size.x; | |
this.wmsParams.height = size.y; | |
var imageSrc = url + L.Util.getParamString(this.wmsParams, url) + "&bbox=" + bbox; | |
this.swapImage(imageSrc, this._futureBounds); | |
}, | |
_reset: function () { | |
var el = this._isSwap ? this._imageSwap : this._image; | |
if (!el){ | |
return; | |
} | |
/** @type {L.LatLng} */ | |
var nwLatLng = this._bounds.getNorthWest(); | |
var seLatLng = this._bounds.getSouthEast(); | |
var topLeft = this._map.latLngToLayerPoint(nwLatLng); | |
var bottomRight = this._map.latLngToLayerPoint(seLatLng); | |
var size = bottomRight.subtract(topLeft); | |
L.DomUtil.setPosition(el, topLeft); | |
el.width = size.x; | |
el.height = size.y; | |
}, | |
_onZoomAnim: function(){ | |
if (this._imageSwap){ | |
this._imageSwap.style.visibility = 'hidden'; | |
} | |
if (this._image){ | |
this._image.style.visibility = 'hidden'; | |
} | |
}, | |
_onSwapImageLoad:function () { | |
if (this._isSwap){ | |
this._imageSwap.style.visibility = 'hidden'; | |
this._image.style.visibility = ''; | |
} else { | |
this._imageSwap.style.visibility = ''; | |
this._image.style.visibility = 'hidden'; | |
} | |
this._isSwap = !this._isSwap; | |
this._bounds = this._futureBounds; | |
this._reset(); | |
}, | |
swapImage:function (src, bounds) { | |
if (!this._imagesCreated){ | |
this._image = this._createImageSwap(); | |
this._imageSwap = this._createImageSwap(); | |
this._imagesCreated = true; | |
} | |
if (this._isSwap){ | |
this._image.src = src; | |
} else { | |
this._imageSwap.src = src; | |
} | |
// do not assign the bound here, this will be done after the next image | |
this._futureBounds = bounds; | |
// allows to re-position the image while waiting for the swap. | |
// attention : the does not work while resizing, because of the wrong bound (size in pixel) | |
this._reset(); | |
}, | |
_createImageSwap:function () { | |
var el = L.DomUtil.create('img', 'leaflet-image-layer'); | |
L.Util.extend(el, { | |
galleryimg: 'no', | |
onselectstart: L.Util.falseFn, | |
onmousemove: L.Util.falseFn, | |
onload: L.Util.bind(this._onSwapImageLoad, this) | |
}); | |
this._map._panes.overlayPane.appendChild(el); | |
el.style.visibility = ''; | |
return el; | |
} | |
}); |
Thank you @fnicollet That SingleTileWMSLayer is exactly what I need and I have made some change on the "onRemove" method.I think we shoud reset "_imagesCreated "status for the next adding. Here is the code.
onRemove: function (map) {
// super()
L.ImageOverlay.prototype.onRemove.call(this, map);
// add
if (this._imageSwap){
map.getPanes().overlayPane.removeChild(this._imageSwap);
}
//reset _imagesCreated status
this._imagesCreated = false;
map.off('moveend', this._onViewReset, this);
map.off('zoomanim', this._onZoomAnim, this);
}
By the way, I use
Leaflet
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for this! It doesn't seem to honor the opacity option as an L.ImageOverlay should. I'm experimenting with adding this._updateOpacity in there somewhere, not exactly sure yet. Or is there just a trick I don't know about?
Currently, I have:
and it will set the opacity correctly every other time I pan.
The reason for this, I discovered, was because
was only applying opacity to
So....
Here's what worked for me - I overrode the this._updateOpacity funtion to apply the opacity to both this._image and this._imageSwap: