esri-leaflet-vector
Version:
Esri vector basemap and vector tile layer plugin for Leaflet.
156 lines (134 loc) • 4.68 kB
JavaScript
import { Layer, setOptions } from "leaflet";
import { loadStyle, formatStyle, isWebMercator } from "./Util.js";
import { maplibreGLJSLayer } from "./MaplibreGLLayer.js";
export const VectorTileLayer = Layer.extend({
options: {
// if portalUrl is not provided, default to ArcGIS Online
portalUrl: "https://www.arcgis.com",
// for performance optimization default to `false`
// set to `true` to resolve printing issues in Firefox
preserveDrawingBuffer: false,
},
/**
* Populates "this.options" to be used in the rest of the module and creates the layer instance.
*
* @param {string} key an ITEM ID or SERVICE URL
* @param {object} options optional
*/
initialize(key, options) {
if (options) {
setOptions(this, options);
}
// support outdated casing apiKey of apikey
if (this.options.apiKey) {
this.options.apikey = this.options.apiKey;
}
// if apiKey is passed in, propagate to token
// if token is passed in, propagate to apiKey
if (this.options.apikey) {
this.options.token = this.options.apikey;
} else if (this.options.token) {
this.options.apikey = this.options.token;
}
// if no key passed in
if (!key) {
throw new Error(
"An ITEM ID or SERVICE URL is required for vectorTileLayer.",
);
}
// set key onto "this.options" for use elsewhere in the module.
if (key) {
this.options.key = key;
}
// this.options has been set, continue on to create the layer:
this._createLayer();
},
/**
* Creates the maplibreGLJSLayer given using "this.options"
*/
_createLayer() {
loadStyle(
this.options.key,
this.options,
(error, style, styleUrl, service) => {
if (error) {
this.fire("load-error", {
value: error,
});
return;
}
if (!isWebMercator(service.tileInfo.spatialReference.wkid)) {
console.warn(
'This layer is not guaranteed to display properly because its service does not use the Web Mercator projection. The "tileInfo.spatialReference" property is:',
service.tileInfo.spatialReference,
"\nMore information is available at https://github.com/maplibre/maplibre-gl-js/issues/168 and https://github.com/Esri/esri-leaflet-vector/issues/94.",
);
}
// once style object is loaded it must be transformed to be compliant with maplibreGLJSLayer
style = formatStyle(style, styleUrl, service, this.options.token);
this._createMaplibreLayer(style);
},
);
},
_setupAttribution() {
// if a custom attribution was not provided in the options,
// then attempt to rely on the attribution of the last source in the style object
// and add it to the map's attribution control
// (otherwise it would have already been added by leaflet to the attribution control)
if (!this.getAttribution()) {
const sources =
this._maplibreGL.getMaplibreMap().style.stylesheet.sources;
const sourcesKeys = Object.keys(sources);
this.options.attribution =
sources[sourcesKeys[sourcesKeys.length - 1]].attribution;
if (this._map && this._map.attributionControl) {
// NOTE: if attribution is an empty string (or otherwise falsy) at this point it would not appear in the attribution control
this._map.attributionControl.addAttribution(this.getAttribution());
}
}
},
_createMaplibreLayer(style) {
this._maplibreGL = maplibreGLJSLayer({
style,
pane: this.options.pane,
opacity: this.options.opacity,
preserveDrawingBuffer: this.options.preserveDrawingBuffer,
});
this._ready = true;
this.fire("ready", {}, true);
this._maplibreGL.on("styleLoaded", () => {
this._setupAttribution();
// additionally modify the style object with the user's optional style override function
if (this.options.style && typeof this.options.style === "function") {
this._maplibreGL._glMap.setStyle(
this.options.style(this._maplibreGL._glMap.getStyle()),
);
}
});
},
onAdd(map) {
this._map = map;
if (this._ready) {
this._asyncAdd();
} else {
this.once(
"ready",
function () {
this._asyncAdd();
},
this,
);
}
},
onRemove(map) {
map.removeLayer(this._maplibreGL);
},
_asyncAdd() {
const map = this._map;
this._maplibreGL.addTo(map, this);
},
});
export function vectorTileLayer(key, options) {
return new VectorTileLayer(key, options);
}
export default vectorTileLayer;