Skip to content

Instantly share code, notes, and snippets.

@apollolm
Forked from fnicollet/gist:5764080
Last active August 29, 2015 13:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save apollolm/8720143 to your computer and use it in GitHub Desktop.
Save apollolm/8720143 to your computer and use it in GitHub Desktop.
DynamicSingleTile is similar to SingleTileWMS overlay for Leaflet map framework, except that it's requesting images from a custom Node.js map server built with mapnik (Chubbs Spatial Server/PGRestAPI)
/*
* from - https://gist.github.com/fnicollet/5764080
* Modified by Ryan Whitley - Jan 30, 2013
* L.DynamicSingleTile uses L.ImageOverlay to display a single-tile layer from node-mapnik.
* url parameter must accept width, height and bbox.
*/
L.DynamicSingleTile = L.ImageOverlay.extend({
initialize: function (url, bounds, options) { // (String, Object)
this._url = url;
if (url.indexOf("{s}") != -1) {
this.options.subdomains = options.subdomains = '1234';
}
this._isSwap = false;
this._imageSwap = null;
L.setOptions(this, options);
},
onAdd: function (map) {
this._map = map;
//
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 size = this._map.getSize();
var b = this._map.getBounds();
var metersBounds = { southWest: L.CRS.EPSG3857.project(b.getSouthWest()), northEast: L.CRS.EPSG3857.project(b.getNorthEast()) };
var imageSrc = this._url + L.Util.getParamString(this.Params, this._url) + "&width=" + size.x + "&height=" + size.y + "&bbox=" + metersBounds.southWest.x + "," + metersBounds.northEast.y + "," + metersBounds.northEast.x + "," + metersBounds.southWest.y;
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();
},
_updateOpacity : function (){
L.DomUtil.setOpacity(this._image, this.options.opacity);
L.DomUtil.setOpacity(this._imageSwap, this.options.opacity);
},
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;
}
this._updateOpacity();
// 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;
}
});
L.dynamicSingleTile = function (url, bounds, options) {
return new L.DynamicSingleTile(url, bounds, options);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment