Geocode with OpenCage and MapLibre
Arnaud Ferrand
Posted on March 22, 2023
OpenCage is an API Provider offering two services a geocoding service and a geosearch service
MapLibre is an Open-source mapping libraries for web and mobile app developers.
In this article we will learn how to geocode with OpenCage and the maplibre-gl-geocoder plugin.
First, one need an OpenCage API Key, it is free for testing, signup for your own key here.
This example will be based on a simple HTML page.
Header
The header will then contain a viewport:
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
Some CSS and JS for MapLibre and the geocoder plugin
<!-- STYLES -->
<link href="https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.css" rel="stylesheet" />
<link href="https://unpkg.com/@maplibre/maplibre-gl-geocoder@1.2.0/dist/maplibre-gl-geocoder.css" rel="stylesheet" />
<!-- scripts -->
<script src="https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.js"></script>
<script src="https://unpkg.com/@maplibre/maplibre-gl-geocoder@1.2.0/dist/maplibre-gl-geocoder.min.js"></script>
<!-- CSS -->
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
Body
Now let's look at the body of this HTML page
<div id="map"></div>
Pretty sleek, isn't it?
Script
Map
Indeed the magic happens in JS. The first part is the map using MapLibre GL JS. Here, I used a simple openstreetmap basemap using a raster source. The SDK offers various sources link.
var map = new maplibregl.Map({
container: "map",
// Use a minimalist raster style
style: {
version: 8,
name: "Blank",
center: [0, 0],
zoom: 0,
sources: {
"raster-tiles": {
type: "raster",
tiles: ["https://tile.openstreetmap.org/{z}/{x}/{y}.png"],
tileSize: 256,
minzoom: 0,
maxzoom: 19
}
},
layers: [
{
id: "background",
type: "background",
paint: {
"background-color": "#e0dfdf"
}
},
{
id: "simple-tiles",
type: "raster",
source: "raster-tiles"
}
],
id: "blank"
},
center: [0, 51],
zoom: 4,
antialias: true
});
Geocode
We define the geocoder API. From the documentation Any geocoder api that supports the functions reverseGeocode and forwardGeocode and returns a response which includes a FeatureCollection of results
We use the OpenCage API and its GeoJSON format, but as you can see, because this is JS, one can use the classical JSON response from the API and transform into GeoJSON.
// Replace it with your API Key.
// The test key returns only
// "Friedrich-Ebert-Straße 7, 48153 Münster, Germany"
// whatever the input is
var YOUR_API_KEY="6d0e711d72d74daeb2b0bfd2a5cdfdba";
var geocoder_api = {
forwardGeocode: async (config) => {
const features = [];
try {
let request =
"https://api.opencagedata.com/geocode/v1/geojson?q=" +
config.query +
"&key="+YOUR_API_KEY+"&no_annotations=1";
const response = await fetch(request);
const geojson = await response.json();
for (let feature of geojson.features) {
let point = {
type: "Feature",
geometry: {
type: "Point",
coordinates: feature.geometry.coordinates
},
place_name: feature.properties.formatted,
properties: feature.properties,
text: feature.properties.formatted,
place_type: ["place"]
};
features.push(point);
}
} catch (e) {
console.error(`Failed to forwardGeocode with error: ${e}`);
}
return {
features: features
};
}
};
now add the Geocoder API to the plugin and attached it to the map
map.addControl(
new MaplibreGeocoder(geocoder_api, {
maplibregl: maplibregl
})
);
and we are all set.
Demo
A live example using the test API key (returning only Münster) is available on codepen
The end
Thanks for reading 🙏
Resources
- The code fragments are available on this gist
- Photo by delfi de la Rua on Unsplash
Posted on March 22, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.