DEV Community

Cover image for Geocode with OpenCage and MapLibre
Arnaud Ferrand
Arnaud Ferrand

Posted on • Edited on

Geocode with OpenCage and MapLibre

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" />
Enter fullscreen mode Exit fullscreen mode

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" />
Enter fullscreen mode Exit fullscreen mode
<!-- 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>
Enter fullscreen mode Exit fullscreen mode
<!-- CSS -->
body {
  margin: 0;
  padding: 0;
}
#map {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
}
Enter fullscreen mode Exit fullscreen mode

Body

Now let's look at the body of this HTML page

<div id="map"></div>
Enter fullscreen mode Exit fullscreen mode

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
});
Enter fullscreen mode Exit fullscreen mode

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
    };
  }
};
Enter fullscreen mode Exit fullscreen mode

now add the Geocoder API to the plugin and attached it to the map

map.addControl(
  new MaplibreGeocoder(geocoder_api, {
    maplibregl: maplibregl
  })
);
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)