OpenCage API and ArcGIS API for JavaScript
Arnaud Ferrand
Posted on May 10, 2020
How to use the OpenCage Data Geocoder API with ArcGIS API for JavaScript
This tutorial will walk you through how to create a map with ArcGIS API for JavaScript and a custom search widget using OpenCage Data Geocoder API.
Get started
We will need a OpenCage Data API key, it is free, signup for your own key here
Your favorite editor: local or online
Local
- VS Code
- Atom
- Sublime Text
- ...
The Mozilla Developer Network has an excellent guide on setting up a local development server.
Online
You can use sites such as CodeSandbox, JS Bin, CodePen and our own ArcGIS API for JavaScript sandbox
Tutorial
Reference the ArcGIS API for JavaScript
First, set up a basic HTML document:
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>ArcGIS Search widget with OpenCage Data API</title>
</head>
<body></body>
</html>
Inside the <head>
tag, reference the ArcGIS API for JavaScript using a <link>
tag:
<link
rel="stylesheet"
href="https://js.arcgis.com/4.15/esri/themes/light/main.css"
/>
Inside the <body>
tag, reference the ArcGIS API for JavaScript using <script>
tag:
<script src="https://js.arcgis.com/4.15/"></script>
Create a map
In the <head>
section add a <style>
tag:
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
In the <body>
section add a <div>
tag before the <script>
tag. This <div>
will be the map view container:
<div id="viewDiv"></div>
At the end of the <body>
, add a <script>
tag and an AMD require
statement to load the Map and MapView
<script>
require(['esri/Map', 'esri/views/MapView'], function (Map, MapView) {
var map = new Map({
basemap: 'topo',
});
var view = new MapView({
container: 'viewDiv',
map: map,
center: [-2.547855, 54.00366], // lon, lat
scale: 4000000,
});
});
</script>
Run your code to view a map centered on the United Kingdom
Add the search widget
In the require
statement, add a reference to the Search module.
require([ 'esri/Map', 'esri/views/MapView', 'esri/widgets/Search' ],
function(Map, MapView, Search) {
At the end of the code in the main function, create a Search
widget and set the view. Add the widget to the top right corner of the view
.
// Search widget
var searchWidget = new Search({
view: view,
});
view.ui.add(searchWidget, 'top-right');
Run the code and try searching for the following:
- London
- Buckingham Palace
- ///index.home.raft (sorry joking, it is a different example)
- -0.20358600,51.521251
Add the custom source : OpenCage Data
In the require
statement, add references to the modules:
- SearchSource the custom source,
- Graphic so the Search widget can display a point result,
- Point used with the Graphic,
- geometryEngine to compute a buffer around the searched location,
- request for the API request to OpenCage Data API.
require([
'esri/Map',
'esri/views/MapView',
'esri/widgets/Search',
'esri/widgets/Search/SearchSource',
'esri/Graphic',
'esri/geometry/Point',
'esri/geometry/geometryEngine',
'esri/request',
], function (
Map,
MapView,
Search,
SearchSource,
Graphic,
Point,
geometryEngine,
esriRequest
) {
// ...
});
Create a function for the geocoding operations at the beginning of the module (AMD require is only here for hint purpose):
require([
// ...
'esri/request',
], function (
// ...
esriRequest
) {
var API_KEY = 'YOUR-API-KEY';
var OPENCAGEDATA_URL = 'https://api.opencagedata.com/geocode/v1/json';
function geocode(options) {
return esriRequest(OPENCAGEDATA_URL, {
query: {
key: API_KEY,
q: options.query,
proximity: options.proximity,
no_annotations: 1,
limit: 6,
},
responseType: 'json',
});
}
// ...
});
Before the Search widget create the custom SearchSource:
// Custom SearchSource
var opencageSearchSource = new SearchSource({
placeholder: 'example: W10',
minSuggestCharacters: 3,
getSuggestions: function (params) {
var address = params.suggestTerm.replace(/ /g, '+');
return geocode({
query: address,
proximity: view.center.latitude + ',' + view.center.longitude,
}).then(function (response) {
var suggestions = response.data.results.map(function (feature) {
return {
key: 'name',
text: feature.formatted,
location: {
longitude: feature.geometry.lng,
latitude: feature.geometry.lat,
},
sourceIndex: params.sourceIndex,
};
});
return suggestions;
});
},
// Provide a getResults method to find
// results from the suggestions, the device location or the text input
getResults: function (params) {
var query;
// Perform a different query if a location is provided
// HTML5 device location or suggestion selected
if (params.location) {
query = params.location.latitude + ',' + params.location.longitude;
} else {
query = params.suggestResult.text.replace(/ /g, '+');
}
return geocode({
query: query,
}).then(function (results) {
// Parse the results of your custom search
var searchResults = results.data.results.map(function (feature) {
// Create a Graphic the Search widget can display
var graphic = new Graphic({
geometry: new Point({
x: feature.geometry.lng,
y: feature.geometry.lat,
}),
attributes: {
name: feature.formatted,
label: feature.formatted,
props: feature.properties,
},
});
var buffer = geometryEngine.geodesicBuffer(
graphic.geometry,
250,
'meters'
);
// Return a Search Result
var searchResult = {
extent: buffer.extent,
feature: graphic,
name: feature.formatted,
};
return searchResult;
});
// Return an array of Search Results
return searchResults;
});
},
});
Update the search widget, disabling the Esri's World Geocoder:
var searchWidget = new Search({
view: view,
sources: [opencageSearchSource],
includeDefaultSources: false,
});
Congratulations, you're done!
Your app should look something like this:
Try searching for the following:
- London
- Buckingham Palace
- 51.521251,-0.20358600 (yes here it is latitude, longitude)
Thank for reading 🙏
You can find the sources in this GitHub repository
-
tutorial.html this step by step tutorial where you only have to change
YOUR-API-KEY
, - index.html an advanced version with an API key prompt, using localStorage for further usage and a basemap widget, as you can also be an addict to the National Geographic basemap, and split files (html, css, js).
Was this post helpful? Don't forget to share because Sharing is Caring.
Resources
- cover image : Photo by Vincent Guth on Unsplash
- OpenCage Data API documentation
- ArcGIS API for Javascript Search widget with custom source
Posted on May 10, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.