How to create Choropleth Maps with Leaflet

Explore how to use Geoapify's Boundary API to fetch and display administrative boundaries on a Leaflet map. This JSFiddle demonstrates how to make API requests using JavaScript and visualize the results on an interactive map.

by Geoapify

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.css">
<div class="header" id="header"></div>
<div class="main">
  <div class="map-container" id="my-map"></div>
</div>

CSS

html,
body {
  margin: 0;
  width: 100%;
  height: 100%;
}

#my-map {
  background: white;
}
 
 .main {
   width: 100%;
   height: 100%;
   display: flex;
   flex-direction: row;
 }
 
 .map-container {
   flex: 1;
   height: 100%;
 }

 
 .header{
    position: absolute;
    pointer-events: none;
    top: 10px;
    left: 100px;
    z-index: 1;
 }
 
 .palette-item {
   display: flex;
   flex-direction: row;
   align-items: center;
   margin: 3px 0;
 }
 
 .palette-item-color {
   width: 30px;
   height: 20px;
   opacity: 0.5;
   border: 2px solid #3e3e3e;
   border-radius: 2px;
   margin-right: 10px;
 }

JavaScript

// Replace the API key with your actual Geoapify API Key obtained from https://myprojects.geoapify.com
const myAPIKey = "6dc7fb95a3b246cfa0f3bcef5ce9ed9a"

// Create a Leaflet map with default view centered at [0, 0] and zoom level 1
const map = L.map("my-map").setView([0, 0], 1)

// OPTIONALLY! Add a base map layer.
/*
// Determine if the device has a Retina display to load appropriate map tiles
const isRetina = L.Browser.retina;

// Define the base URLs for standard and Retina-quality map tiles
const baseUrl = "https://maps.geoapify.com/v1/tile/osm-bright/{z}/{x}/{y}.png?apiKey={apiKey}";
const retinaUrl = "https://maps.geoapify.com/v1/tile/osm-bright/{z}/{x}/{y}@2x.png?apiKey={apiKey}";

// Find more map styles here - https://apidocs.geoapify.com/docs/maps/map-tiles/#about

L.tileLayer(isRetina ? retinaUrl : baseUrl, {
  attribution: 'Powered by <a href="https://www.geoapify.com/" target="_blank">Geoapify</a> | <a href="http://openmaptiles.org/" target="_blank">© OpenMapTiles</a>  <a href="https://www.openstreetmap.org/copyright" target="_blank">© OpenStreetMap</a> contributors',
  apiKey: myAPIKey,
  maxZoom: 20,
  id: 'osm-bright',
}).addTo(map);
*/

// Specify the place (e.g., "California") for which you want to retrieve administrative boundaries
const place = "Brittany, France"
const sublevel = 2

// Call the function to fetch administrative divisions using Geoapify's Geocoding API
getAdministrativeDivisions(place)

// palette
const palette = [
  "#B7EFC5",
  "#92E6A7",
  "#6EDE8A",
  "#4AD66D",
  "#2DC653",
  "#25A244",
  "#208B3A",
  "#1A7431",
  "#155D27",
  "#10451D",
]

buildLegend()

async function getAdministrativeDivisions(place) {
  // Fetch place data (including place ID and bounding box) using Geoapify's Geocoding API
  const placeData = await fetch(
    `https://api.geoapify.com/v1/geocode/search?text=${encodeURIComponent(place)}&limit=1&apiKey=${myAPIKey}`,
  ).then((result) => result.json())

  if (placeData && placeData.features.length) {
  ...