Find places
Learn how to search for coffee shops, gas stations, restaurants and other nearby places with the geocoding service.
Place finding is the process of searching for a place name or POI to find its address and location. You can use the geocoding service to find places such as coffee shops, gas stations, or restaurants for any geographic location around the world. You can search for places by name or by using categories. You can search near a location or you can search globally.
In this tutorial, you use ArcGIS REST JS to access the geocoding service and find places by place category.
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 basemapId = "ArcGIS:Streets"; const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey; olms(map, basemapURL);
Add references to ArcGIS REST JS
This tutorial uses ArcGIS REST JS for place finding.
In the
<head>
element, add references to the ArcGIS REST JS library.Add line. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" /> <title>OpenLayers Tutorials: Find Places</title> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" /> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script> <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></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-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> </head> <body> <div id="map"></div> <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;"> <option value="">Choose a place type...</option> <option value="Coffee shop">Coffee shops</option> <option value="Gas station">Gas stations</option> <option value="Food">Food</option> <option value="Hotel">Hotels</option> <option value="Parks and Outdoors">Parks and Outdoors</option> </select> <script> const apiKey = "YOUR-API-KEY"; const map = new ol.Map({ target: "map" }); const view = new ol.View({ center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco zoom: 14 }); map.setView(view); const basemapId = "ArcGIS:Navigation"; const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey; olms(map, basemapURL).then(function (map) { const placesLayer = new ol.layer.Vector({ source: new ol.source.Vector(), style: (feature) => new ol.style.Style({ image: new ol.style.Circle({ radius: 5, fill: new ol.style.Fill({ color: "white" }), stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 }) }), text: new ol.style.Text({ font: "14px sans-serif", textAlign: "left", text: feature.get("PlaceName"), offsetX: 8, // move text to the right to avoid overlapping circle offsetY: 2, // move down to align with circle's center fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }), stroke: new ol.style.Stroke({ color: "white" }) }) }), declutter: true }); map.addLayer(placesLayer); function showPlaces() { const authentication = new arcgisRest.ApiKey({ key: apiKey }); const category = document.getElementById("places-select").value; arcgisRest .geocode({ authentication, outFields: "Place_addr,PlaceName", // attributes to be returned params: { category, location: ol.proj.toLonLat(view.getCenter()), maxLocations: 25 } }) .then((response) => { const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson); placesLayer.getSource().clear(); placesLayer.getSource().addFeatures(features); }) .catch((error) => { alert("There was a problem using the geocoder. See the console for details."); console.error(error); }); } document.getElementById("places-select").addEventListener("change", showPlaces); }); </script> </body> </html>
Update the map
A navigation basemap layer is typically used in geocoding and routing applications. Update the basemap layer to use ArcGIS:Navigation
.
Update the basemap and the map initialization to center on location
[-122.4194,37.7749]
, San Francisco.Change line Change line <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" /> <title>OpenLayers Tutorials: Find Places</title> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" /> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script> <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></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-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> </head> <body> <div id="map"></div> <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;"> <option value="">Choose a place type...</option> <option value="Coffee shop">Coffee shops</option> <option value="Gas station">Gas stations</option> <option value="Food">Food</option> <option value="Hotel">Hotels</option> <option value="Parks and Outdoors">Parks and Outdoors</option> </select> <script> const apiKey = "YOUR-API-KEY"; const map = new ol.Map({ target: "map" }); const view = new ol.View({ center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco zoom: 14 }); map.setView(view); const basemapId = "ArcGIS:Navigation"; const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey; olms(map, basemapURL).then(function (map) { const placesLayer = new ol.layer.Vector({ source: new ol.source.Vector(), style: (feature) => new ol.style.Style({ image: new ol.style.Circle({ radius: 5, fill: new ol.style.Fill({ color: "white" }), stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 }) }), text: new ol.style.Text({ font: "14px sans-serif", textAlign: "left", text: feature.get("PlaceName"), offsetX: 8, // move text to the right to avoid overlapping circle offsetY: 2, // move down to align with circle's center fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }), stroke: new ol.style.Stroke({ color: "white" }) }) }), declutter: true }); map.addLayer(placesLayer); function showPlaces() { const authentication = new arcgisRest.ApiKey({ key: apiKey }); const category = document.getElementById("places-select").value; arcgisRest .geocode({ authentication, outFields: "Place_addr,PlaceName", // attributes to be returned params: { category, location: ol.proj.toLonLat(view.getCenter()), maxLocations: 25 } }) .then((response) => { const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson); placesLayer.getSource().clear(); placesLayer.getSource().addFeatures(features); }) .catch((error) => { alert("There was a problem using the geocoder. See the console for details."); console.error(error); }); } document.getElementById("places-select").addEventListener("change", showPlaces); }); </script> </body> </html>
Add controls
Use a select
element to create the drop-down element. Each category is an option
element inside it. The select
element needs to have absolute
positioning in order to appear in front of the map element.
Add a
select
control, with options for "Coffee shop", "Gas station", "Food", "Hotel", "Parks and outdoors". Use inline styling to position the control.The option values have special meaning to the geocoding service so ensure the spelling is correct. See the ArcGIS REST API documentation for details.
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" /> <title>OpenLayers Tutorials: Find Places</title> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" /> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script> <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></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-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> </head> <body> <div id="map"></div> <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;"> <option value="">Choose a place type...</option> <option value="Coffee shop">Coffee shops</option> <option value="Gas station">Gas stations</option> <option value="Food">Food</option> <option value="Hotel">Hotels</option> <option value="Parks and Outdoors">Parks and Outdoors</option> </select> <script> const apiKey = "YOUR-API-KEY"; const map = new ol.Map({ target: "map" }); const view = new ol.View({ center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco zoom: 14 }); map.setView(view); const basemapId = "ArcGIS:Navigation"; const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey; olms(map, basemapURL).then(function (map) { const placesLayer = new ol.layer.Vector({ source: new ol.source.Vector(), style: (feature) => new ol.style.Style({ image: new ol.style.Circle({ radius: 5, fill: new ol.style.Fill({ color: "white" }), stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 }) }), text: new ol.style.Text({ font: "14px sans-serif", textAlign: "left", text: feature.get("PlaceName"), offsetX: 8, // move text to the right to avoid overlapping circle offsetY: 2, // move down to align with circle's center fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }), stroke: new ol.style.Stroke({ color: "white" }) }) }), declutter: true }); map.addLayer(placesLayer); function showPlaces() { const authentication = new arcgisRest.ApiKey({ key: apiKey }); const category = document.getElementById("places-select").value; arcgisRest .geocode({ authentication, outFields: "Place_addr,PlaceName", // attributes to be returned params: { category, location: ol.proj.toLonLat(view.getCenter()), maxLocations: 25 } }) .then((response) => { const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson); placesLayer.getSource().clear(); placesLayer.getSource().addFeatures(features); }) .catch((error) => { alert("There was a problem using the geocoder. See the console for details."); console.error(error); }); } document.getElementById("places-select").addEventListener("change", showPlaces); }); </script> </body> </html>
At the top right, click Run to verify that the
select
control is created and contains the different categories.
Add a places layer
To display places from the geocoding service on the map, you will add a vector layer, containing a vector source. Small blue circles is the default styling used.
Add a map load handler to the initial
olms
function call. Inside, create a new vector layer containing a vector source. Store it in aplacesLayer
, and add it to the map withmap.addLayer
;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" /> <title>OpenLayers Tutorials: Find Places</title> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" /> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script> <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></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-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> </head> <body> <div id="map"></div> <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;"> <option value="">Choose a place type...</option> <option value="Coffee shop">Coffee shops</option> <option value="Gas station">Gas stations</option> <option value="Food">Food</option> <option value="Hotel">Hotels</option> <option value="Parks and Outdoors">Parks and Outdoors</option> </select> <script> const apiKey = "YOUR-API-KEY"; const map = new ol.Map({ target: "map" }); const view = new ol.View({ center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco zoom: 14 }); map.setView(view); const basemapId = "ArcGIS:Navigation"; const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey; olms(map, basemapURL).then(function (map) { const placesLayer = new ol.layer.Vector({ source: new ol.source.Vector(), style: (feature) => new ol.style.Style({ image: new ol.style.Circle({ radius: 5, fill: new ol.style.Fill({ color: "white" }), stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 }) }), text: new ol.style.Text({ font: "14px sans-serif", textAlign: "left", text: feature.get("PlaceName"), offsetX: 8, // move text to the right to avoid overlapping circle offsetY: 2, // move down to align with circle's center fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }), stroke: new ol.style.Stroke({ color: "white" }) }) }), declutter: true }); map.addLayer(placesLayer); function showPlaces() { const authentication = new arcgisRest.ApiKey({ key: apiKey }); const category = document.getElementById("places-select").value; arcgisRest .geocode({ authentication, outFields: "Place_addr,PlaceName", // attributes to be returned params: { category, location: ol.proj.toLonLat(view.getCenter()), maxLocations: 25 } }) .then((response) => { const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson); placesLayer.getSource().clear(); placesLayer.getSource().addFeatures(features); }) .catch((error) => { alert("There was a problem using the geocoder. See the console for details."); console.error(error); }); } document.getElementById("places-select").addEventListener("change", showPlaces); }); </script> </body> </html>
Call the geocoding service
To find places near a location, you can use the arcgisRest.geocode
. Use the center of the map view.getCenter
with proj.toLonLat
to get the point in longitude and latitude. Provide the category selected by the user using document.getElementById
to get the control, then use its value
property.
Create a function called
showPlaces
. Inside, create a newarcgisRest.ApiKey
to access the geocoding service. CallarcgisRest.geocode()
to set the API key and to call the service endpoint. Passlocation
andcategory
, and specifyPlace_addr
andPlaceName
as the fields to be returned. Request a maximum of 25 places.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" /> <title>OpenLayers Tutorials: Find Places</title> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" /> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script> <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></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-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> </head> <body> <div id="map"></div> <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;"> <option value="">Choose a place type...</option> <option value="Coffee shop">Coffee shops</option> <option value="Gas station">Gas stations</option> <option value="Food">Food</option> <option value="Hotel">Hotels</option> <option value="Parks and Outdoors">Parks and Outdoors</option> </select> <script> const apiKey = "YOUR-API-KEY"; const map = new ol.Map({ target: "map" }); const view = new ol.View({ center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco zoom: 14 }); map.setView(view); const basemapId = "ArcGIS:Navigation"; const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey; olms(map, basemapURL).then(function (map) { const placesLayer = new ol.layer.Vector({ source: new ol.source.Vector(), style: (feature) => new ol.style.Style({ image: new ol.style.Circle({ radius: 5, fill: new ol.style.Fill({ color: "white" }), stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 }) }), text: new ol.style.Text({ font: "14px sans-serif", textAlign: "left", text: feature.get("PlaceName"), offsetX: 8, // move text to the right to avoid overlapping circle offsetY: 2, // move down to align with circle's center fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }), stroke: new ol.style.Stroke({ color: "white" }) }) }), declutter: true }); map.addLayer(placesLayer); function showPlaces() { const authentication = new arcgisRest.ApiKey({ key: apiKey }); const category = document.getElementById("places-select").value; arcgisRest .geocode({ authentication, outFields: "Place_addr,PlaceName", // attributes to be returned params: { category, location: ol.proj.toLonLat(view.getCenter()), maxLocations: 25 } }) .then((response) => { const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson); placesLayer.getSource().clear(); placesLayer.getSource().addFeatures(features); }) .catch((error) => { alert("There was a problem using the geocoder. See the console for details."); console.error(error); }); } document.getElementById("places-select").addEventListener("change", showPlaces); }); </script> </body> </html>
Display results
When the query completes, the geoJson
property of the response object contains a GeoJSON feature collection of points. You can use this to update the data of your places
source. You will need to use a GeoJSON
feature format to read the data, and also reproject it to the map's projection. Use an exception handler to detect problems accessing the service. This could happen due to network disruption or a problem with your API key, for instance.
Add a response handler. Inside, use a new GeoJSON feature format to read the
geoJson
property and reproject the data. Clear the places source withclear
and add the new features withaddFeatures
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" /> <title>OpenLayers Tutorials: Find Places</title> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" /> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script> <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></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-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> </head> <body> <div id="map"></div> <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;"> <option value="">Choose a place type...</option> <option value="Coffee shop">Coffee shops</option> <option value="Gas station">Gas stations</option> <option value="Food">Food</option> <option value="Hotel">Hotels</option> <option value="Parks and Outdoors">Parks and Outdoors</option> </select> <script> const apiKey = "YOUR-API-KEY"; const map = new ol.Map({ target: "map" }); const view = new ol.View({ center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco zoom: 14 }); map.setView(view); const basemapId = "ArcGIS:Navigation"; const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey; olms(map, basemapURL).then(function (map) { const placesLayer = new ol.layer.Vector({ source: new ol.source.Vector(), style: (feature) => new ol.style.Style({ image: new ol.style.Circle({ radius: 5, fill: new ol.style.Fill({ color: "white" }), stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 }) }), text: new ol.style.Text({ font: "14px sans-serif", textAlign: "left", text: feature.get("PlaceName"), offsetX: 8, // move text to the right to avoid overlapping circle offsetY: 2, // move down to align with circle's center fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }), stroke: new ol.style.Stroke({ color: "white" }) }) }), declutter: true }); map.addLayer(placesLayer); function showPlaces() { const authentication = new arcgisRest.ApiKey({ key: apiKey }); const category = document.getElementById("places-select").value; arcgisRest .geocode({ authentication, outFields: "Place_addr,PlaceName", // attributes to be returned params: { category, location: ol.proj.toLonLat(view.getCenter()), maxLocations: 25 } }) .then((response) => { const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson); placesLayer.getSource().clear(); placesLayer.getSource().addFeatures(features); }) .catch((error) => { alert("There was a problem using the geocoder. See the console for details."); console.error(error); }); } document.getElementById("places-select").addEventListener("change", showPlaces); }); </script> </body> </html>
If there is an exception accessing the geocoding service, alert the user and log the error.
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" /> <title>OpenLayers Tutorials: Find Places</title> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" /> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script> <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></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-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> </head> <body> <div id="map"></div> <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;"> <option value="">Choose a place type...</option> <option value="Coffee shop">Coffee shops</option> <option value="Gas station">Gas stations</option> <option value="Food">Food</option> <option value="Hotel">Hotels</option> <option value="Parks and Outdoors">Parks and Outdoors</option> </select> <script> const apiKey = "YOUR-API-KEY"; const map = new ol.Map({ target: "map" }); const view = new ol.View({ center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco zoom: 14 }); map.setView(view); const basemapId = "ArcGIS:Navigation"; const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey; olms(map, basemapURL).then(function (map) { const placesLayer = new ol.layer.Vector({ source: new ol.source.Vector(), style: (feature) => new ol.style.Style({ image: new ol.style.Circle({ radius: 5, fill: new ol.style.Fill({ color: "white" }), stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 }) }), text: new ol.style.Text({ font: "14px sans-serif", textAlign: "left", text: feature.get("PlaceName"), offsetX: 8, // move text to the right to avoid overlapping circle offsetY: 2, // move down to align with circle's center fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }), stroke: new ol.style.Stroke({ color: "white" }) }) }), declutter: true }); map.addLayer(placesLayer); function showPlaces() { const authentication = new arcgisRest.ApiKey({ key: apiKey }); const category = document.getElementById("places-select").value; arcgisRest .geocode({ authentication, outFields: "Place_addr,PlaceName", // attributes to be returned params: { category, location: ol.proj.toLonLat(view.getCenter()), maxLocations: 25 } }) .then((response) => { const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson); placesLayer.getSource().clear(); placesLayer.getSource().addFeatures(features); }) .catch((error) => { alert("There was a problem using the geocoder. See the console for details."); console.error(error); }); } document.getElementById("places-select").addEventListener("change", showPlaces); }); </script> </body> </html>
Add a change event handler
To update the map when the user chooses a category, you must add an event handler for the change
event on the <select>
control.
After the map initialization code, add
showPlaces
as thechange
event handler to the<select>
control.Add line. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" /> <title>OpenLayers Tutorials: Find Places</title> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" /> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script> <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></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-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> </head> <body> <div id="map"></div> <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;"> <option value="">Choose a place type...</option> <option value="Coffee shop">Coffee shops</option> <option value="Gas station">Gas stations</option> <option value="Food">Food</option> <option value="Hotel">Hotels</option> <option value="Parks and Outdoors">Parks and Outdoors</option> </select> <script> const apiKey = "YOUR-API-KEY"; const map = new ol.Map({ target: "map" }); const view = new ol.View({ center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco zoom: 14 }); map.setView(view); const basemapId = "ArcGIS:Navigation"; const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey; olms(map, basemapURL).then(function (map) { const placesLayer = new ol.layer.Vector({ source: new ol.source.Vector(), style: (feature) => new ol.style.Style({ image: new ol.style.Circle({ radius: 5, fill: new ol.style.Fill({ color: "white" }), stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 }) }), text: new ol.style.Text({ font: "14px sans-serif", textAlign: "left", text: feature.get("PlaceName"), offsetX: 8, // move text to the right to avoid overlapping circle offsetY: 2, // move down to align with circle's center fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }), stroke: new ol.style.Stroke({ color: "white" }) }) }), declutter: true }); map.addLayer(placesLayer); function showPlaces() { const authentication = new arcgisRest.ApiKey({ key: apiKey }); const category = document.getElementById("places-select").value; arcgisRest .geocode({ authentication, outFields: "Place_addr,PlaceName", // attributes to be returned params: { category, location: ol.proj.toLonLat(view.getCenter()), maxLocations: 25 } }) .then((response) => { const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson); placesLayer.getSource().clear(); placesLayer.getSource().addFeatures(features); }) .catch((error) => { alert("There was a problem using the geocoder. See the console for details."); console.error(error); }); } document.getElementById("places-select").addEventListener("change", showPlaces); }); </script> </body> </html>
At the top right, click Run. When you choose a place category, circles should be shown for places.
Display labels
In order to show the name of each place on the map, you will modify the layer definition to include a style
property. You provide a function that takes a feature and returns a Style
. It will include a Text
style to display the labels, using the text
property to determine which is text is displayed. Use the PlaceName
property of the feature for this. You will also set properties such as textAlign
and font
to control the appearance of the labels. The style will also include a Circle
style to draw a circle at the place location.
By default, the labels would overlap each other and be hard to read. You use the declutter
property on the Vector
layer to prevent this.
Add a
style
property to theplacesLayer
definition. Make this function return a newStyle
which includes aCircle
style and aText
style for theimage
andtext
properties. Enable thedeclutter
setting.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" /> <title>OpenLayers Tutorials: Find Places</title> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" /> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script> <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></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-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script> </head> <body> <div id="map"></div> <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;"> <option value="">Choose a place type...</option> <option value="Coffee shop">Coffee shops</option> <option value="Gas station">Gas stations</option> <option value="Food">Food</option> <option value="Hotel">Hotels</option> <option value="Parks and Outdoors">Parks and Outdoors</option> </select> <script> const apiKey = "YOUR-API-KEY"; const map = new ol.Map({ target: "map" }); const view = new ol.View({ center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco zoom: 14 }); map.setView(view); const basemapId = "ArcGIS:Navigation"; const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey; olms(map, basemapURL).then(function (map) { const placesLayer = new ol.layer.Vector({ source: new ol.source.Vector(), style: (feature) => new ol.style.Style({ image: new ol.style.Circle({ radius: 5, fill: new ol.style.Fill({ color: "white" }), stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 }) }), text: new ol.style.Text({ font: "14px sans-serif", textAlign: "left", text: feature.get("PlaceName"), offsetX: 8, // move text to the right to avoid overlapping circle offsetY: 2, // move down to align with circle's center fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }), stroke: new ol.style.Stroke({ color: "white" }) }) }), declutter: true }); map.addLayer(placesLayer); function showPlaces() { const authentication = new arcgisRest.ApiKey({ key: apiKey }); const category = document.getElementById("places-select").value; arcgisRest .geocode({ authentication, outFields: "Place_addr,PlaceName", // attributes to be returned params: { category, location: ol.proj.toLonLat(view.getCenter()), maxLocations: 25 } }) .then((response) => { const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson); placesLayer.getSource().clear(); placesLayer.getSource().addFeatures(features); }) .catch((error) => { alert("There was a problem using the geocoder. See the console for details."); console.error(error); }); } document.getElementById("places-select").addEventListener("change", showPlaces); }); </script> </body> </html>
Run the app
In CodePen, run your code to display the map.
When you choose a place category, you should see the name of each place shown as a label, next to a white circle with a blue outline.
What's next?
Learn how to use additional ArcGIS location services in these tutorials: