esri-leaflet
Version:
Leaflet plugins for consuming ArcGIS Online and ArcGIS Server services.
257 lines (214 loc) • 6.98 kB
JavaScript
import L from 'leaflet';
import { cors } from '../Support';
import { setEsriAttribution } from '../Util';
var Overlay = L.ImageOverlay.extend({
onAdd: function (map) {
this._topLeft = map.getPixelBounds().min;
L.ImageOverlay.prototype.onAdd.call(this, map);
},
_reset: function () {
if (this._map.options.crs === L.CRS.EPSG3857) {
L.ImageOverlay.prototype._reset.call(this);
} else {
L.DomUtil.setPosition(this._image, this._topLeft.subtract(this._map.getPixelOrigin()));
}
}
});
export var RasterLayer = L.Layer.extend({
options: {
opacity: 1,
position: 'front',
f: 'image',
useCors: cors,
attribution: null,
interactive: false,
alt: ''
},
onAdd: function (map) {
// include 'Powered by Esri' in map attribution
setEsriAttribution(map);
this._update = L.Util.throttle(this._update, this.options.updateInterval, this);
map.on('moveend', this._update, this);
// if we had an image loaded and it matches the
// current bounds show the image otherwise remove it
if (this._currentImage && this._currentImage._bounds.equals(this._map.getBounds())) {
map.addLayer(this._currentImage);
} else if (this._currentImage) {
this._map.removeLayer(this._currentImage);
this._currentImage = null;
}
this._update();
if (this._popup) {
this._map.on('click', this._getPopupData, this);
this._map.on('dblclick', this._resetPopupState, this);
}
// add copyright text listed in service metadata
this.metadata(function (err, metadata) {
if (!err && !this.options.attribution && map.attributionControl && metadata.copyrightText) {
this.options.attribution = metadata.copyrightText;
map.attributionControl.addAttribution(this.getAttribution());
}
}, this);
},
onRemove: function (map) {
if (this._currentImage) {
this._map.removeLayer(this._currentImage);
}
if (this._popup) {
this._map.off('click', this._getPopupData, this);
this._map.off('dblclick', this._resetPopupState, this);
}
this._map.off('moveend', this._update, this);
},
bindPopup: function (fn, popupOptions) {
this._shouldRenderPopup = false;
this._lastClick = false;
this._popup = L.popup(popupOptions);
this._popupFunction = fn;
if (this._map) {
this._map.on('click', this._getPopupData, this);
this._map.on('dblclick', this._resetPopupState, this);
}
return this;
},
unbindPopup: function () {
if (this._map) {
this._map.closePopup(this._popup);
this._map.off('click', this._getPopupData, this);
this._map.off('dblclick', this._resetPopupState, this);
}
this._popup = false;
return this;
},
bringToFront: function () {
this.options.position = 'front';
if (this._currentImage) {
this._currentImage.bringToFront();
}
return this;
},
bringToBack: function () {
this.options.position = 'back';
if (this._currentImage) {
this._currentImage.bringToBack();
}
return this;
},
getAttribution: function () {
return this.options.attribution;
},
getOpacity: function () {
return this.options.opacity;
},
setOpacity: function (opacity) {
this.options.opacity = opacity;
this._currentImage.setOpacity(opacity);
return this;
},
getTimeRange: function () {
return [this.options.from, this.options.to];
},
setTimeRange: function (from, to) {
this.options.from = from;
this.options.to = to;
this._update();
return this;
},
metadata: function (callback, context) {
this.service.metadata(callback, context);
return this;
},
authenticate: function (token) {
this.service.authenticate(token);
return this;
},
_renderImage: function (url, bounds, contentType) {
if (this._map) {
// if no output directory has been specified for a service, MIME data will be returned
if (contentType) {
url = 'data:' + contentType + ';base64,' + url;
}
// create a new image overlay and add it to the map
// to start loading the image
// opacity is 0 while the image is loading
var image = new Overlay(url, bounds, {
opacity: 0,
crossOrigin: this.options.useCors,
alt: this.options.alt,
pane: this.options.pane || this.getPane(),
interactive: this.options.interactive
}).addTo(this._map);
// once the image loads
image.once('load', function (e) {
if (this._map) {
var newImage = e.target;
var oldImage = this._currentImage;
// if the bounds of this image matches the bounds that
// _renderImage was called with and we have a map with the same bounds
// hide the old image if there is one and set the opacity
// of the new image otherwise remove the new image
if (newImage._bounds.equals(bounds) && newImage._bounds.equals(this._map.getBounds())) {
this._currentImage = newImage;
if (this.options.position === 'front') {
this.bringToFront();
} else {
this.bringToBack();
}
if (this._map && this._currentImage._map) {
this._currentImage.setOpacity(this.options.opacity);
} else {
this._currentImage._map.removeLayer(this._currentImage);
}
if (oldImage && this._map) {
this._map.removeLayer(oldImage);
}
if (oldImage && oldImage._map) {
oldImage._map.removeLayer(oldImage);
}
} else {
this._map.removeLayer(newImage);
}
}
this.fire('load', {
bounds: bounds
});
}, this);
this.fire('loading', {
bounds: bounds
});
}
},
_update: function () {
if (!this._map) {
return;
}
var zoom = this._map.getZoom();
var bounds = this._map.getBounds();
if (this._animatingZoom) {
return;
}
if (this._map._panTransition && this._map._panTransition._inProgress) {
return;
}
if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
this._currentImage._map.removeLayer(this._currentImage);
return;
}
var params = this._buildExportParams();
this._requestExport(params, bounds);
},
_renderPopup: function (latlng, error, results, response) {
latlng = L.latLng(latlng);
if (this._shouldRenderPopup && this._lastClick.equals(latlng)) {
// add the popup to the map where the mouse was clicked at
var content = this._popupFunction(error, results, response);
if (content) {
this._popup.setLatLng(latlng).setContent(content).openOn(this._map);
}
}
},
_resetPopupState: function (e) {
this._shouldRenderPopup = false;
this._lastClick = e.latlng;
}
});