Query a feature layer (spatial)
Learn how to execute a spatial query to access polygon features from a feature service.
A feature layer can contain a large number of features stored in ArcGIS. To access a subset of these features, you can execute an SQL or spatial query, either together or individually. The results can contain the attributes, geometry, or both for each record. SQL and spatial queries are useful when a feature layer is very large and you want to access only a subset of its data.
In this tutorial, you use Mapbox GL Draw to sketch a feature on the map, and then use ArcGIS REST JS to perform a spatial query against the LA County Parcels hosted feature layer. The layer contains ±2.4 million features. The spatial query returns all of the parcels that intersect the sketched feature. A pop-up is also used to display feature attributes.
Prerequisites
You need a free ArcGIS developer account to access your dashboard and API keys. The API key must be scoped to access the services used in this tutorial.
Steps
Create a new pen
- To get started, either complete the Display a map tutorial or .
Set the API key
To access ArcGIS location services, you need an API key.
Go to your dashboard to get an API key.
In CodePen, update
apiKey
to use your key.Change line // const apiKey = "YOUR-API-KEY"; const basemapEnum = "ArcGIS:Streets"; const map = new mapboxgl.Map({ container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`, zoom: 12, // starting zoom center: [-118.805, 34.027] // starting location [longitude, latitude] });
Add script references
This tutorial uses three sets of libraries. ArcGIS REST JS is used for querying the feature layer. Mapbox GL Draw provides drawing tools, allowing the user to define a point, line, or polygon of interest. Terraformer is used to convert GeoJSON features generated by Mapbox GL Draw into ArcGIS JSON geometries; a requirement to query the feature layer service.
Add
<script>
tags to reference the libraries.Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script> <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" /> <link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.css" type="text/css" /> <script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-feature-layer@3.0.0/dist/umd/feature-layer.umd.js"></script> <script src="https://unpkg.com/@terraformer/arcgis@2.0.7/dist/t-arcgis.umd.js"></script> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> </head> <body> <div id="map"></div> <script> const apiKey = "YOUR-API-KEY"; const basemapEnum = "ArcGIS:Streets"; const map = new mapboxgl.Map({ container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`, zoom: 12, // starting zoom center: [-118.80543, 34.03] // starting location [longitude, latitude] }); const draw = new MapboxDraw({ displayControlsDefault: false, // Don't add any tools other than those below controls: { point: true, line_string: true, polygon: true } }); map.addControl(draw, "top-left"); function addQueryLayers() { map.addSource("query", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "query-line", type: "line", source: "query", paint: { "line-color": "hsl(140, 0%, 30%)", "line-width": 2, "line-dasharray": [2,2] } }); map.addLayer({ id: "query-fill", type: "fill", source: "query", paint: { "fill-color": "hsl(140, 0%, 50%)", "fill-opacity": 0.2 }, filter: ["==", ["geometry-type"], "Polygon"] }); map.addLayer({ id: "query-circle", type: "circle", source: "query", paint: { "circle-color": "hsl(140, 0%, 30%)" }, filter: ["==", ["geometry-type"], "Point"] }); } function addParcelLayers() { map.addSource("parcels", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "parcels-fill", source: "parcels", type: "fill", paint: { "fill-color": "hsl(200, 80%, 50%)", "fill-opacity": 0.5, "fill-outline-color": "white" } }); } map.on("load", () => { addParcelLayers(); addQueryLayers(); }); map.on("draw.create", (e) => { const feature = e.features[0]; map.getSource("query").setData(feature); draw.deleteAll(); const geometry = Terraformer.geojsonToArcGIS(feature.geometry); let geometryType = "esriGeometry" + feature.geometry.type; if (feature.geometry.type === "LineString") { geometryType = "esriGeometryPolyline"; } executeQuery(geometry, geometryType); }); function executeQuery(geometry, geometryType) { arcgisRest .queryFeatures({ url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0", geometry: geometry, geometryType: geometryType, spatialRel: "esriSpatialRelIntersects", f: "geojson", returnGeometry: true, outFields: ["APN", "UseType", "TaxRateCity", " Roll_LandValue"] }) .then((response) => { map.getSource("parcels").setData(response); }); } map.on("click", "parcels-fill", (e) => { const p = e.features[0].properties; const message = `<b>Parcel ${p.APN}</b>` + `Type: ${p.UseType} <br>` + `Land value: $${p.Roll_LandValue.toLocaleString()} <br>` + `Tax Rate City: ${p.TaxRateCity}`; new mapboxgl.Popup() .setHTML(message) .setLngLat(e.lngLat) .addTo(map); }); </script> </body> </html>
Add Mapbox GL Draw
To display the Mapbox GL Draw controls, create a MapboxDraw
and call map.addControl
. By default, other tools are included, so you need to specify the three required tools: point, line, and polygon.
Create a
MapboxDraw
and add it to theMap
.Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script> <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" /> <link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.css" type="text/css" /> <script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-feature-layer@3.0.0/dist/umd/feature-layer.umd.js"></script> <script src="https://unpkg.com/@terraformer/arcgis@2.0.7/dist/t-arcgis.umd.js"></script> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> </head> <body> <div id="map"></div> <script> const apiKey = "YOUR-API-KEY"; const basemapEnum = "ArcGIS:Streets"; const map = new mapboxgl.Map({ container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`, zoom: 12, // starting zoom center: [-118.80543, 34.03] // starting location [longitude, latitude] }); const draw = new MapboxDraw({ displayControlsDefault: false, // Don't add any tools other than those below controls: { point: true, line_string: true, polygon: true } }); map.addControl(draw, "top-left"); function addQueryLayers() { map.addSource("query", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "query-line", type: "line", source: "query", paint: { "line-color": "hsl(140, 0%, 30%)", "line-width": 2, "line-dasharray": [2,2] } }); map.addLayer({ id: "query-fill", type: "fill", source: "query", paint: { "fill-color": "hsl(140, 0%, 50%)", "fill-opacity": 0.2 }, filter: ["==", ["geometry-type"], "Polygon"] }); map.addLayer({ id: "query-circle", type: "circle", source: "query", paint: { "circle-color": "hsl(140, 0%, 30%)" }, filter: ["==", ["geometry-type"], "Point"] }); } function addParcelLayers() { map.addSource("parcels", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "parcels-fill", source: "parcels", type: "fill", paint: { "fill-color": "hsl(200, 80%, 50%)", "fill-opacity": 0.5, "fill-outline-color": "white" } }); } map.on("load", () => { addParcelLayers(); addQueryLayers(); }); map.on("draw.create", (e) => { const feature = e.features[0]; map.getSource("query").setData(feature); draw.deleteAll(); const geometry = Terraformer.geojsonToArcGIS(feature.geometry); let geometryType = "esriGeometry" + feature.geometry.type; if (feature.geometry.type === "LineString") { geometryType = "esriGeometryPolyline"; } executeQuery(geometry, geometryType); }); function executeQuery(geometry, geometryType) { arcgisRest .queryFeatures({ url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0", geometry: geometry, geometryType: geometryType, spatialRel: "esriSpatialRelIntersects", f: "geojson", returnGeometry: true, outFields: ["APN", "UseType", "TaxRateCity", " Roll_LandValue"] }) .then((response) => { map.getSource("parcels").setData(response); }); } map.on("click", "parcels-fill", (e) => { const p = e.features[0].properties; const message = `<b>Parcel ${p.APN}</b>` + `Type: ${p.UseType} <br>` + `Land value: $${p.Roll_LandValue.toLocaleString()} <br>` + `Tax Rate City: ${p.TaxRateCity}`; new mapboxgl.Popup() .setHTML(message) .setLngLat(e.lngLat) .addTo(map); }); </script> </body> </html>
Add query layers
Three layers are required to display the three types of query you can perform: circle, line, and fill. They share a single GeoJSON source, which at any time will contain one feature of either Point
, LineString
or Polygon
geometry. Create the source with an empty GeoJSON feature collection.
A line layer can display both line features and the border of polygon features.
The circle layer should be filtered to only display point features. Otherwise, a circle will be shown at each vertex of line and polygon features. You can use a filter and the ['geometry-type']
expression. See the Mapbox GL Style Specification for more details.
Similarly, the fill layer should be filtered to only display polygon features. Otherwise, line features will be treated as polygons and filled inappropriately.
Create an
addQueryLayers
function. Inside, add a GeoJSON source and circle, line, and fill layersAdd line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script> <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" /> <link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.css" type="text/css" /> <script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-feature-layer@3.0.0/dist/umd/feature-layer.umd.js"></script> <script src="https://unpkg.com/@terraformer/arcgis@2.0.7/dist/t-arcgis.umd.js"></script> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> </head> <body> <div id="map"></div> <script> const apiKey = "YOUR-API-KEY"; const basemapEnum = "ArcGIS:Streets"; const map = new mapboxgl.Map({ container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`, zoom: 12, // starting zoom center: [-118.80543, 34.03] // starting location [longitude, latitude] }); const draw = new MapboxDraw({ displayControlsDefault: false, // Don't add any tools other than those below controls: { point: true, line_string: true, polygon: true } }); map.addControl(draw, "top-left"); function addQueryLayers() { map.addSource("query", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "query-line", type: "line", source: "query", paint: { "line-color": "hsl(140, 0%, 30%)", "line-width": 2, "line-dasharray": [2,2] } }); map.addLayer({ id: "query-fill", type: "fill", source: "query", paint: { "fill-color": "hsl(140, 0%, 50%)", "fill-opacity": 0.2 }, filter: ["==", ["geometry-type"], "Polygon"] }); map.addLayer({ id: "query-circle", type: "circle", source: "query", paint: { "circle-color": "hsl(140, 0%, 30%)" }, filter: ["==", ["geometry-type"], "Point"] }); } function addParcelLayers() { map.addSource("parcels", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "parcels-fill", source: "parcels", type: "fill", paint: { "fill-color": "hsl(200, 80%, 50%)", "fill-opacity": 0.5, "fill-outline-color": "white" } }); } map.on("load", () => { addParcelLayers(); addQueryLayers(); }); map.on("draw.create", (e) => { const feature = e.features[0]; map.getSource("query").setData(feature); draw.deleteAll(); const geometry = Terraformer.geojsonToArcGIS(feature.geometry); let geometryType = "esriGeometry" + feature.geometry.type; if (feature.geometry.type === "LineString") { geometryType = "esriGeometryPolyline"; } executeQuery(geometry, geometryType); }); function executeQuery(geometry, geometryType) { arcgisRest .queryFeatures({ url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0", geometry: geometry, geometryType: geometryType, spatialRel: "esriSpatialRelIntersects", f: "geojson", returnGeometry: true, outFields: ["APN", "UseType", "TaxRateCity", " Roll_LandValue"] }) .then((response) => { map.getSource("parcels").setData(response); }); } map.on("click", "parcels-fill", (e) => { const p = e.features[0].properties; const message = `<b>Parcel ${p.APN}</b>` + `Type: ${p.UseType} <br>` + `Land value: $${p.Roll_LandValue.toLocaleString()} <br>` + `Tax Rate City: ${p.TaxRateCity}`; new mapboxgl.Popup() .setHTML(message) .setLngLat(e.lngLat) .addTo(map); }); </script> </body> </html>
Add parcel layers
Parcels returned by the query are simple polygons. You can display them with a GeoJSON source and a fill layer.
Create an
addParcelLayers
function. Inside, add a GeoJSON source and a fill layer.Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script> <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" /> <link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.css" type="text/css" /> <script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-feature-layer@3.0.0/dist/umd/feature-layer.umd.js"></script> <script src="https://unpkg.com/@terraformer/arcgis@2.0.7/dist/t-arcgis.umd.js"></script> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> </head> <body> <div id="map"></div> <script> const apiKey = "YOUR-API-KEY"; const basemapEnum = "ArcGIS:Streets"; const map = new mapboxgl.Map({ container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`, zoom: 12, // starting zoom center: [-118.80543, 34.03] // starting location [longitude, latitude] }); const draw = new MapboxDraw({ displayControlsDefault: false, // Don't add any tools other than those below controls: { point: true, line_string: true, polygon: true } }); map.addControl(draw, "top-left"); function addQueryLayers() { map.addSource("query", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "query-line", type: "line", source: "query", paint: { "line-color": "hsl(140, 0%, 30%)", "line-width": 2, "line-dasharray": [2,2] } }); map.addLayer({ id: "query-fill", type: "fill", source: "query", paint: { "fill-color": "hsl(140, 0%, 50%)", "fill-opacity": 0.2 }, filter: ["==", ["geometry-type"], "Polygon"] }); map.addLayer({ id: "query-circle", type: "circle", source: "query", paint: { "circle-color": "hsl(140, 0%, 30%)" }, filter: ["==", ["geometry-type"], "Point"] }); } function addParcelLayers() { map.addSource("parcels", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "parcels-fill", source: "parcels", type: "fill", paint: { "fill-color": "hsl(200, 80%, 50%)", "fill-opacity": 0.5, "fill-outline-color": "white" } }); } map.on("load", () => { addParcelLayers(); addQueryLayers(); }); map.on("draw.create", (e) => { const feature = e.features[0]; map.getSource("query").setData(feature); draw.deleteAll(); const geometry = Terraformer.geojsonToArcGIS(feature.geometry); let geometryType = "esriGeometry" + feature.geometry.type; if (feature.geometry.type === "LineString") { geometryType = "esriGeometryPolyline"; } executeQuery(geometry, geometryType); }); function executeQuery(geometry, geometryType) { arcgisRest .queryFeatures({ url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0", geometry: geometry, geometryType: geometryType, spatialRel: "esriSpatialRelIntersects", f: "geojson", returnGeometry: true, outFields: ["APN", "UseType", "TaxRateCity", " Roll_LandValue"] }) .then((response) => { map.getSource("parcels").setData(response); }); } map.on("click", "parcels-fill", (e) => { const p = e.features[0].properties; const message = `<b>Parcel ${p.APN}</b>` + `Type: ${p.UseType} <br>` + `Land value: $${p.Roll_LandValue.toLocaleString()} <br>` + `Tax Rate City: ${p.TaxRateCity}`; new mapboxgl.Popup() .setHTML(message) .setLngLat(e.lngLat) .addTo(map); }); </script> </body> </html>
Add a load handler
To add layers to the map, use the load
event to ensure the map is fully loaded.
Add an event handler for the
load
event. Inside, calladdQueryLayers
andaddParcelLayers
;Add line. Add line. Add line. Add line. Add line. Add line. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script> <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" /> <link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.css" type="text/css" /> <script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-feature-layer@3.0.0/dist/umd/feature-layer.umd.js"></script> <script src="https://unpkg.com/@terraformer/arcgis@2.0.7/dist/t-arcgis.umd.js"></script> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> </head> <body> <div id="map"></div> <script> const apiKey = "YOUR-API-KEY"; const basemapEnum = "ArcGIS:Streets"; const map = new mapboxgl.Map({ container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`, zoom: 12, // starting zoom center: [-118.80543, 34.03] // starting location [longitude, latitude] }); const draw = new MapboxDraw({ displayControlsDefault: false, // Don't add any tools other than those below controls: { point: true, line_string: true, polygon: true } }); map.addControl(draw, "top-left"); function addQueryLayers() { map.addSource("query", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "query-line", type: "line", source: "query", paint: { "line-color": "hsl(140, 0%, 30%)", "line-width": 2, "line-dasharray": [2,2] } }); map.addLayer({ id: "query-fill", type: "fill", source: "query", paint: { "fill-color": "hsl(140, 0%, 50%)", "fill-opacity": 0.2 }, filter: ["==", ["geometry-type"], "Polygon"] }); map.addLayer({ id: "query-circle", type: "circle", source: "query", paint: { "circle-color": "hsl(140, 0%, 30%)" }, filter: ["==", ["geometry-type"], "Point"] }); } function addParcelLayers() { map.addSource("parcels", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "parcels-fill", source: "parcels", type: "fill", paint: { "fill-color": "hsl(200, 80%, 50%)", "fill-opacity": 0.5, "fill-outline-color": "white" } }); } map.on("load", () => { addParcelLayers(); addQueryLayers(); }); map.on("draw.create", (e) => { const feature = e.features[0]; map.getSource("query").setData(feature); draw.deleteAll(); const geometry = Terraformer.geojsonToArcGIS(feature.geometry); let geometryType = "esriGeometry" + feature.geometry.type; if (feature.geometry.type === "LineString") { geometryType = "esriGeometryPolyline"; } executeQuery(geometry, geometryType); }); function executeQuery(geometry, geometryType) { arcgisRest .queryFeatures({ url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0", geometry: geometry, geometryType: geometryType, spatialRel: "esriSpatialRelIntersects", f: "geojson", returnGeometry: true, outFields: ["APN", "UseType", "TaxRateCity", " Roll_LandValue"] }) .then((response) => { map.getSource("parcels").setData(response); }); } map.on("click", "parcels-fill", (e) => { const p = e.features[0].properties; const message = `<b>Parcel ${p.APN}</b>` + `Type: ${p.UseType} <br>` + `Land value: $${p.Roll_LandValue.toLocaleString()} <br>` + `Tax Rate City: ${p.TaxRateCity}`; new mapboxgl.Popup() .setHTML(message) .setLngLat(e.lngLat) .addTo(map); }); </script> </body> </html>
Get the draw feature
Mapbox GL Draw emits a draw.create
event when you have finished drawing a feature. You can listen to this event to respond to the newly created feature.
By default, Mapbox GL Draw keeps all previously drawn features visible in its own layer. To prevent this, use deleteAll
after copying the feature.
Add an event handler for
draw.create
. Inside, store the feature in thequery
layer, then delete all features from Mapbox GL Draw.Add line. Add line. Add line. Add line. Add line. Add line. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script> <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" /> <link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.css" type="text/css" /> <script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-feature-layer@3.0.0/dist/umd/feature-layer.umd.js"></script> <script src="https://unpkg.com/@terraformer/arcgis@2.0.7/dist/t-arcgis.umd.js"></script> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> </head> <body> <div id="map"></div> <script> const apiKey = "YOUR-API-KEY"; const basemapEnum = "ArcGIS:Streets"; const map = new mapboxgl.Map({ container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`, zoom: 12, // starting zoom center: [-118.80543, 34.03] // starting location [longitude, latitude] }); const draw = new MapboxDraw({ displayControlsDefault: false, // Don't add any tools other than those below controls: { point: true, line_string: true, polygon: true } }); map.addControl(draw, "top-left"); function addQueryLayers() { map.addSource("query", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "query-line", type: "line", source: "query", paint: { "line-color": "hsl(140, 0%, 30%)", "line-width": 2, "line-dasharray": [2,2] } }); map.addLayer({ id: "query-fill", type: "fill", source: "query", paint: { "fill-color": "hsl(140, 0%, 50%)", "fill-opacity": 0.2 }, filter: ["==", ["geometry-type"], "Polygon"] }); map.addLayer({ id: "query-circle", type: "circle", source: "query", paint: { "circle-color": "hsl(140, 0%, 30%)" }, filter: ["==", ["geometry-type"], "Point"] }); } function addParcelLayers() { map.addSource("parcels", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "parcels-fill", source: "parcels", type: "fill", paint: { "fill-color": "hsl(200, 80%, 50%)", "fill-opacity": 0.5, "fill-outline-color": "white" } }); } map.on("load", () => { addParcelLayers(); addQueryLayers(); }); map.on("draw.create", (e) => { const feature = e.features[0]; map.getSource("query").setData(feature); draw.deleteAll(); const geometry = Terraformer.geojsonToArcGIS(feature.geometry); let geometryType = "esriGeometry" + feature.geometry.type; if (feature.geometry.type === "LineString") { geometryType = "esriGeometryPolyline"; } executeQuery(geometry, geometryType); }); function executeQuery(geometry, geometryType) { arcgisRest .queryFeatures({ url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0", geometry: geometry, geometryType: geometryType, spatialRel: "esriSpatialRelIntersects", f: "geojson", returnGeometry: true, outFields: ["APN", "UseType", "TaxRateCity", " Roll_LandValue"] }) .then((response) => { map.getSource("parcels").setData(response); }); } map.on("click", "parcels-fill", (e) => { const p = e.features[0].properties; const message = `<b>Parcel ${p.APN}</b>` + `Type: ${p.UseType} <br>` + `Land value: $${p.Roll_LandValue.toLocaleString()} <br>` + `Tax Rate City: ${p.TaxRateCity}`; new mapboxgl.Popup() .setHTML(message) .setLngLat(e.lngLat) .addTo(map); }); </script> </body> </html>
Click Run at the top right to test your code. You should be able to sketch a point, line or polygon feature, and see it turn into a green feature when complete.
Execute the query
Use the ArcGIS REST JS queryFeatures method to find features in the LA County Parcels feature layer that intersect the sketched feature. Use Terraformer.geojsonToArcGIS to convert the GeoJSON from Mapbox GL Draw into the ArcGIS geometry format.
When the matching parcels are returned, you can call setData
on the parcels source to display them.
Create a function called
executeQuery
withgeometry
andgeometryType
parameters. Inside, create a newarcgisRest.ApiKey
to access the feature service. CallarcgisRest.queryFeatures
. Pass thegeometry
andgeometryType
. Specify GeoJSON as the return type, requestingreturnGeometry
and specificoutFields
. All of the features within the geometry will be returned with attribute information set by theoutFields
property.There are many other spatial relationships that you can specify with
spatialRel
. For example, you can useesriSpatialRelContains
to only return parcels within the sketched polygon. See the ArcGIS REST API documentation for details.Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script> <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" /> <link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.css" type="text/css" /> <script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-feature-layer@3.0.0/dist/umd/feature-layer.umd.js"></script> <script src="https://unpkg.com/@terraformer/arcgis@2.0.7/dist/t-arcgis.umd.js"></script> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> </head> <body> <div id="map"></div> <script> const apiKey = "YOUR-API-KEY"; const basemapEnum = "ArcGIS:Streets"; const map = new mapboxgl.Map({ container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`, zoom: 12, // starting zoom center: [-118.80543, 34.03] // starting location [longitude, latitude] }); const draw = new MapboxDraw({ displayControlsDefault: false, // Don't add any tools other than those below controls: { point: true, line_string: true, polygon: true } }); map.addControl(draw, "top-left"); function addQueryLayers() { map.addSource("query", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "query-line", type: "line", source: "query", paint: { "line-color": "hsl(140, 0%, 30%)", "line-width": 2, "line-dasharray": [2,2] } }); map.addLayer({ id: "query-fill", type: "fill", source: "query", paint: { "fill-color": "hsl(140, 0%, 50%)", "fill-opacity": 0.2 }, filter: ["==", ["geometry-type"], "Polygon"] }); map.addLayer({ id: "query-circle", type: "circle", source: "query", paint: { "circle-color": "hsl(140, 0%, 30%)" }, filter: ["==", ["geometry-type"], "Point"] }); } function addParcelLayers() { map.addSource("parcels", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "parcels-fill", source: "parcels", type: "fill", paint: { "fill-color": "hsl(200, 80%, 50%)", "fill-opacity": 0.5, "fill-outline-color": "white" } }); } map.on("load", () => { addParcelLayers(); addQueryLayers(); }); map.on("draw.create", (e) => { const feature = e.features[0]; map.getSource("query").setData(feature); draw.deleteAll(); const geometry = Terraformer.geojsonToArcGIS(feature.geometry); let geometryType = "esriGeometry" + feature.geometry.type; if (feature.geometry.type === "LineString") { geometryType = "esriGeometryPolyline"; } executeQuery(geometry, geometryType); }); function executeQuery(geometry, geometryType) { arcgisRest .queryFeatures({ url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0", geometry: geometry, geometryType: geometryType, spatialRel: "esriSpatialRelIntersects", f: "geojson", returnGeometry: true, outFields: ["APN", "UseType", "TaxRateCity", " Roll_LandValue"] }) .then((response) => { map.getSource("parcels").setData(response); }); } map.on("click", "parcels-fill", (e) => { const p = e.features[0].properties; const message = `<b>Parcel ${p.APN}</b>` + `Type: ${p.UseType} <br>` + `Land value: $${p.Roll_LandValue.toLocaleString()} <br>` + `Tax Rate City: ${p.TaxRateCity}`; new mapboxgl.Popup() .setHTML(message) .setLngLat(e.lngLat) .addTo(map); }); </script> </body> </html>
Add a response handler. Inside, set the returned parcels as the data for the parcels source.
Add line. Add line. Add line. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script> <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" /> <link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.css" type="text/css" /> <script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-feature-layer@3.0.0/dist/umd/feature-layer.umd.js"></script> <script src="https://unpkg.com/@terraformer/arcgis@2.0.7/dist/t-arcgis.umd.js"></script> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> </head> <body> <div id="map"></div> <script> const apiKey = "YOUR-API-KEY"; const basemapEnum = "ArcGIS:Streets"; const map = new mapboxgl.Map({ container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`, zoom: 12, // starting zoom center: [-118.80543, 34.03] // starting location [longitude, latitude] }); const draw = new MapboxDraw({ displayControlsDefault: false, // Don't add any tools other than those below controls: { point: true, line_string: true, polygon: true } }); map.addControl(draw, "top-left"); function addQueryLayers() { map.addSource("query", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "query-line", type: "line", source: "query", paint: { "line-color": "hsl(140, 0%, 30%)", "line-width": 2, "line-dasharray": [2,2] } }); map.addLayer({ id: "query-fill", type: "fill", source: "query", paint: { "fill-color": "hsl(140, 0%, 50%)", "fill-opacity": 0.2 }, filter: ["==", ["geometry-type"], "Polygon"] }); map.addLayer({ id: "query-circle", type: "circle", source: "query", paint: { "circle-color": "hsl(140, 0%, 30%)" }, filter: ["==", ["geometry-type"], "Point"] }); } function addParcelLayers() { map.addSource("parcels", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "parcels-fill", source: "parcels", type: "fill", paint: { "fill-color": "hsl(200, 80%, 50%)", "fill-opacity": 0.5, "fill-outline-color": "white" } }); } map.on("load", () => { addParcelLayers(); addQueryLayers(); }); map.on("draw.create", (e) => { const feature = e.features[0]; map.getSource("query").setData(feature); draw.deleteAll(); const geometry = Terraformer.geojsonToArcGIS(feature.geometry); let geometryType = "esriGeometry" + feature.geometry.type; if (feature.geometry.type === "LineString") { geometryType = "esriGeometryPolyline"; } executeQuery(geometry, geometryType); }); function executeQuery(geometry, geometryType) { arcgisRest .queryFeatures({ url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0", geometry: geometry, geometryType: geometryType, spatialRel: "esriSpatialRelIntersects", f: "geojson", returnGeometry: true, outFields: ["APN", "UseType", "TaxRateCity", " Roll_LandValue"] }) .then((response) => { map.getSource("parcels").setData(response); }); } map.on("click", "parcels-fill", (e) => { const p = e.features[0].properties; const message = `<b>Parcel ${p.APN}</b>` + `Type: ${p.UseType} <br>` + `Land value: $${p.Roll_LandValue.toLocaleString()} <br>` + `Tax Rate City: ${p.TaxRateCity}`; new mapboxgl.Popup() .setHTML(message) .setLngLat(e.lngLat) .addTo(map); }); </script> </body> </html>
In your MapboxDraw event handler, call
executeQuery
. UseTerraformer.geojsonToArcGIS
to convertgeometry
into an ArcGIS JSON format.Add line. Add line. Add line. Add line. Add line. Add line. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script> <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" /> <link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.css" type="text/css" /> <script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-feature-layer@3.0.0/dist/umd/feature-layer.umd.js"></script> <script src="https://unpkg.com/@terraformer/arcgis@2.0.7/dist/t-arcgis.umd.js"></script> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> </head> <body> <div id="map"></div> <script> const apiKey = "YOUR-API-KEY"; const basemapEnum = "ArcGIS:Streets"; const map = new mapboxgl.Map({ container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`, zoom: 12, // starting zoom center: [-118.80543, 34.03] // starting location [longitude, latitude] }); const draw = new MapboxDraw({ displayControlsDefault: false, // Don't add any tools other than those below controls: { point: true, line_string: true, polygon: true } }); map.addControl(draw, "top-left"); function addQueryLayers() { map.addSource("query", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "query-line", type: "line", source: "query", paint: { "line-color": "hsl(140, 0%, 30%)", "line-width": 2, "line-dasharray": [2,2] } }); map.addLayer({ id: "query-fill", type: "fill", source: "query", paint: { "fill-color": "hsl(140, 0%, 50%)", "fill-opacity": 0.2 }, filter: ["==", ["geometry-type"], "Polygon"] }); map.addLayer({ id: "query-circle", type: "circle", source: "query", paint: { "circle-color": "hsl(140, 0%, 30%)" }, filter: ["==", ["geometry-type"], "Point"] }); } function addParcelLayers() { map.addSource("parcels", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "parcels-fill", source: "parcels", type: "fill", paint: { "fill-color": "hsl(200, 80%, 50%)", "fill-opacity": 0.5, "fill-outline-color": "white" } }); } map.on("load", () => { addParcelLayers(); addQueryLayers(); }); map.on("draw.create", (e) => { const feature = e.features[0]; map.getSource("query").setData(feature); draw.deleteAll(); const geometry = Terraformer.geojsonToArcGIS(feature.geometry); let geometryType = "esriGeometry" + feature.geometry.type; if (feature.geometry.type === "LineString") { geometryType = "esriGeometryPolyline"; } executeQuery(geometry, geometryType); }); function executeQuery(geometry, geometryType) { arcgisRest .queryFeatures({ url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0", geometry: geometry, geometryType: geometryType, spatialRel: "esriSpatialRelIntersects", f: "geojson", returnGeometry: true, outFields: ["APN", "UseType", "TaxRateCity", " Roll_LandValue"] }) .then((response) => { map.getSource("parcels").setData(response); }); } map.on("click", "parcels-fill", (e) => { const p = e.features[0].properties; const message = `<b>Parcel ${p.APN}</b>` + `Type: ${p.UseType} <br>` + `Land value: $${p.Roll_LandValue.toLocaleString()} <br>` + `Tax Rate City: ${p.TaxRateCity}`; new mapboxgl.Popup() .setHTML(message) .setLngLat(e.lngLat) .addTo(map); }); </script> </body> </html>
At the top right, click Run. When you create a feature using the toolbox, a spatial query will run against the feature layer and display all land parcels within the boundary of the feature.
Add a pop-up
You can add a pop-up to view attributes of a parcel when you click on it.
Add a
click
event handler to theparcels-fill
layer. Inside, construct the pop-up content from the attributes of the clicked parcel.Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script> <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" /> <link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.css" type="text/css" /> <script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-feature-layer@3.0.0/dist/umd/feature-layer.umd.js"></script> <script src="https://unpkg.com/@terraformer/arcgis@2.0.7/dist/t-arcgis.umd.js"></script> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> </head> <body> <div id="map"></div> <script> const apiKey = "YOUR-API-KEY"; const basemapEnum = "ArcGIS:Streets"; const map = new mapboxgl.Map({ container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`, zoom: 12, // starting zoom center: [-118.80543, 34.03] // starting location [longitude, latitude] }); const draw = new MapboxDraw({ displayControlsDefault: false, // Don't add any tools other than those below controls: { point: true, line_string: true, polygon: true } }); map.addControl(draw, "top-left"); function addQueryLayers() { map.addSource("query", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "query-line", type: "line", source: "query", paint: { "line-color": "hsl(140, 0%, 30%)", "line-width": 2, "line-dasharray": [2,2] } }); map.addLayer({ id: "query-fill", type: "fill", source: "query", paint: { "fill-color": "hsl(140, 0%, 50%)", "fill-opacity": 0.2 }, filter: ["==", ["geometry-type"], "Polygon"] }); map.addLayer({ id: "query-circle", type: "circle", source: "query", paint: { "circle-color": "hsl(140, 0%, 30%)" }, filter: ["==", ["geometry-type"], "Point"] }); } function addParcelLayers() { map.addSource("parcels", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "parcels-fill", source: "parcels", type: "fill", paint: { "fill-color": "hsl(200, 80%, 50%)", "fill-opacity": 0.5, "fill-outline-color": "white" } }); } map.on("load", () => { addParcelLayers(); addQueryLayers(); }); map.on("draw.create", (e) => { const feature = e.features[0]; map.getSource("query").setData(feature); draw.deleteAll(); const geometry = Terraformer.geojsonToArcGIS(feature.geometry); let geometryType = "esriGeometry" + feature.geometry.type; if (feature.geometry.type === "LineString") { geometryType = "esriGeometryPolyline"; } executeQuery(geometry, geometryType); }); function executeQuery(geometry, geometryType) { arcgisRest .queryFeatures({ url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0", geometry: geometry, geometryType: geometryType, spatialRel: "esriSpatialRelIntersects", f: "geojson", returnGeometry: true, outFields: ["APN", "UseType", "TaxRateCity", " Roll_LandValue"] }) .then((response) => { map.getSource("parcels").setData(response); }); } map.on("click", "parcels-fill", (e) => { const p = e.features[0].properties; const message = `<b>Parcel ${p.APN}</b>` + `Type: ${p.UseType} <br>` + `Land value: $${p.Roll_LandValue.toLocaleString()} <br>` + `Tax Rate City: ${p.TaxRateCity}`; new mapboxgl.Popup() .setHTML(message) .setLngLat(e.lngLat) .addTo(map); }); </script> </body> </html>
Create a Popup. Use
Popup.setHTML
to set the content. Update the position of the pop-up usingPopup.setLngLat
, and add it to the map usingPopup.addTo
.Add line. Add line. Add line. Add line. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script> <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" /> <link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.css" type="text/css" /> <script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-feature-layer@3.0.0/dist/umd/feature-layer.umd.js"></script> <script src="https://unpkg.com/@terraformer/arcgis@2.0.7/dist/t-arcgis.umd.js"></script> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> </head> <body> <div id="map"></div> <script> const apiKey = "YOUR-API-KEY"; const basemapEnum = "ArcGIS:Streets"; const map = new mapboxgl.Map({ container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`, zoom: 12, // starting zoom center: [-118.80543, 34.03] // starting location [longitude, latitude] }); const draw = new MapboxDraw({ displayControlsDefault: false, // Don't add any tools other than those below controls: { point: true, line_string: true, polygon: true } }); map.addControl(draw, "top-left"); function addQueryLayers() { map.addSource("query", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "query-line", type: "line", source: "query", paint: { "line-color": "hsl(140, 0%, 30%)", "line-width": 2, "line-dasharray": [2,2] } }); map.addLayer({ id: "query-fill", type: "fill", source: "query", paint: { "fill-color": "hsl(140, 0%, 50%)", "fill-opacity": 0.2 }, filter: ["==", ["geometry-type"], "Polygon"] }); map.addLayer({ id: "query-circle", type: "circle", source: "query", paint: { "circle-color": "hsl(140, 0%, 30%)" }, filter: ["==", ["geometry-type"], "Point"] }); } function addParcelLayers() { map.addSource("parcels", { type: "geojson", data: { type: