diff --git a/CHANGELOG.md b/CHANGELOG.md index f97602e..dcabd04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added +* `L.esri.Vector.vectorTileLayer` has been extended to support vector tiles layers hosted in ArcGIS Enterprise. A new `portalUrl` layer constructor option was added and is intended to be used with the "ITEM_ID" constructor flavor. [#97](https://github.com/Esri/esri-leaflet-vector/pull/97) + * New README documentation and a developer console warning for `L.esri.Vector.vectorTileLayer` explaining that only services with a Web Mercator `spatialReference` are fully supported. [#95](https://github.com/Esri/esri-leaflet-vector/pull/95) ## [3.0.1] - 2021-06-03 diff --git a/README.md b/README.md index 69adf3b..1b9e777 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Take a look at the [live demo](https://esri.github.io/esri-leaflet/examples/vect var map = L.map("map").setView([40.706, -73.926], 14); L.esri.Vector.vectorBasemapLayer("ArcGIS:Streets", { - apikey: "< YOUR VALID API KEY HERE >", + apikey: "< YOUR VALID API KEY HERE >" }).addTo(map); @@ -67,17 +67,22 @@ Take a look at the [live demo](https://esri.github.io/esri-leaflet/examples/vect For rendering basemap layers which use the Esri Basemap Styles API internally. Extends [L.Layer](https://leafletjs.com/reference#layer). + ```javascript +// example using an Esri Basemap Styles API name L.esri.Vector.vectorBasemapLayer("ArcGIS:Streets", { - // provide either apikey or token + // provide either `apikey` or `token` apikey: "...", - token: "...", + token: "..." }).addTo(map); +``` +```javascript +// example using an ITEM_ID L.esri.Vector.vectorBasemapLayer("ITEM_ID", { - // provide either apikey or token + // provide either `apikey` or `token` apikey: "...", - token: "...", + token: "..." }).addTo(map); ``` @@ -92,25 +97,41 @@ For custom vector tiles layers published from user data. Extends [L.Layer](https :warning: This only supports services using the Web Mercator projection because it [relies directly upon `mapbox-gl-js v1`](#dependencies). Otherwise, the layer is not guaranteed to display properly. More information is available at and . ```javascript +// example using an ITEM_ID L.esri.Vector.vectorTileLayer("ITEM_ID", { - // provide either apikey or token if not public + // optional: provide either `apikey` or `token` if not public apikey: "...", token: "...", - // optionally customize the style with a function that gets the default style from the service + + // optional: if your layer is not hosted on ArcGIS Online, + // change `portalUrl` to the ArcGIS Enterprise base url + // (this is necessary when specifying an ITEM_ID) + portalUrl: "https://www.arcgis.com", // default value + + // optional: customize the style with a function that gets the default style from the service // and returns the new style to be used style: (style) => { return newStyle; } }).addTo(map); +``` +```javascript +// example using a VectorTileServer SERVICE_URL L.esri.Vector.vectorTileLayer("SERVICE_URL", { - // provide either apikey or token if not public + // optional: provide either `apikey` or `token` if not public apikey: "...", token: "...", - // optionally customize the style with a function that gets the default style from the service + + // optional: if your layer is not hosted on ArcGIS Online, + // change `portalUrl` to the ArcGIS Enterprise base url + // (this may not be necessary when specifying a SERVICE_URL) + portalUrl: "https://www.arcgis.com", // default value + + // optional: customize the style with a function that gets the default style from the service // and returns the new style to be used style: (style) => { - return newStyle + return newStyle; } }).addTo(map); ``` diff --git a/spec/VectorTileLayerSpec.js b/spec/VectorTileLayerSpec.js index 838ac82..2b4e30b 100644 --- a/spec/VectorTileLayerSpec.js +++ b/spec/VectorTileLayerSpec.js @@ -5,6 +5,11 @@ var serviceUrl = 'https://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/se var token = '1234abcd'; var apikey = 'dcba4321'; +// for layers hosted in ArcGIS Enterprise instead of ArcGIS Online +var onPremisePortalUrl = 'https://PATH/TO/ARCGIS/ENTERPRISE'; // defaults to https://www.arcgis.com +var onPremiseItemId = '1c365daf37a744fbad748b67aa69dac8'; +var onPremiseServiceUrl = 'https://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/Microsoft_Building_Footprints/VectorTileServer'; + describe('VectorTileLayer', function () { it('should have a L.esri.vectorTileLayer alias', function () { console.log('L.esri.Vector.vectorTileLayer', L.esri.Vector.vectorTileLayer); @@ -64,4 +69,32 @@ describe('VectorTileLayer', function () { expect(layer.options.pane).to.equal(otherPane); }); + + it('should default to ArcGIS Online as the base "portalUrl" for loading the style - itemId', function () { + const layer = L.esri.Vector.vectorTileLayer(itemId); + + expect(layer.options.portalUrl).to.equal('https://www.arcgis.com'); + }); + + it('should default to ArcGIS Online as the base "portalUrl" for loading the style - serviceUrl', function () { + const layer = L.esri.Vector.vectorTileLayer(serviceUrl); + + expect(layer.options.portalUrl).to.equal('https://www.arcgis.com'); + }); + + it('should let the base "portalUrl" be changed in the constructor for loading an on-premise style - itemId', function () { + const layer = L.esri.Vector.vectorTileLayer(onPremiseItemId, { + portalUrl: onPremisePortalUrl + }); + + expect(layer.options.portalUrl).to.equal(onPremisePortalUrl); + }); + + it('should let the base "portalUrl" be changed in the constructor for loading an on-premise style - serviceUrl', function () { + const layer = L.esri.Vector.vectorTileLayer(onPremiseServiceUrl, { + portalUrl: onPremisePortalUrl + }); + + expect(layer.options.portalUrl).to.equal(onPremisePortalUrl); + }); }); diff --git a/src/Util.js b/src/Util.js index 3b2ea61..d8e2e4a 100644 --- a/src/Util.js +++ b/src/Util.js @@ -42,13 +42,16 @@ export function loadService (serviceUrl, options, callback) { function loadItem (itemId, options, callback) { var params = options.token ? { token: options.token } : {}; - var url = 'https://www.arcgis.com/sharing/rest/content/items/' + itemId; + var url = options.portalUrl + + '/sharing/rest/content/items/' + + itemId; request(url, params, callback); } function loadStyleFromItem (itemId, options, callback) { var itemStyleUrl = - 'https://www.arcgis.com/sharing/rest/content/items/' + + options.portalUrl + + '/sharing/rest/content/items/' + itemId + '/resources/styles/root.json'; @@ -128,8 +131,12 @@ export function formatStyle (style, styleUrl, metadata, token) { source.tiles = [source.url + metadata.tiles[0]]; } + // some VectorTileServer endpoints may default to returning f=html, + // specify f=json to account for that behavior + source.url += '?f=json'; + // add the token to the source url and tiles properties as a query param - source.url += token ? '?token=' + token : ''; + source.url += token ? '&token=' + token : ''; source.tiles[0] += token ? '?token=' + token : ''; // add minzoom and maxzoom to each source based on the service metadata diff --git a/src/VectorTileLayer.js b/src/VectorTileLayer.js index 02a57ac..aa1627e 100644 --- a/src/VectorTileLayer.js +++ b/src/VectorTileLayer.js @@ -4,9 +4,12 @@ import { mapboxGLJSLayer } from './MapBoxGLLayer'; export var VectorTileLayer = Layer.extend({ options: { - // if pane is not provided default to LeafletJS's overlayPane + // if pane is not provided, default to LeafletJS's overlayPane // https://leafletjs.com/reference.html#map-pane - pane: 'overlayPane' + pane: 'overlayPane', + + // if portalUrl is not provided, default to ArcGIS Online + portalUrl: 'https://www.arcgis.com' }, /**