Interactive choropleth map

Create an interactive choropleth map by utilizing events and feature states. Utilize events and feature states to develop an engaging choropleth map.

Enhance the level of interaction in your choropleth map by integrating an informative box that showcases the name of the state and its population density. Additionally, learn how to generate a legend that effectively represents the various values and categories depicted on the choropleth map.

<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Choropleth Map</title>
<script src="https://cdn.maptiler.com/maptiler-sdk-js/v3.0.1/maptiler-sdk.umd.min.js"></script>
<link href="https://cdn.maptiler.com/maptiler-sdk-js/v3.0.1/maptiler-sdk.css" rel="stylesheet" />
<style>
  body {margin: 0; padding: 0;}
  #map {position: absolute; top: 0; bottom: 0; width: 100%;}
  h2,
  h3 {
    margin: 10px;
    font-size: 18px;
  }
  h3 {
    font-size: 16px;
  }
  p {
    margin: 10px;
  }
  .overlay {
    position: absolute;
    bottom: 0;
    left: 0;
    background: #fff;
    margin-left: 20px;
    font-family: Arial, sans-serif;
    overflow: auto;
    border-radius: 3px;
  }
  #legend {
    padding: 10px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
    margin-bottom: 20px;
  }
  #legend h4 {
    margin: 0 0 10px;
  }
  #legend div span {
    display: inline-block;
    height: 20px;
    width: 30px;
    margin: 0 -2.5px;
  }
  #legend div.labels {
    margin-left: -20px;
  }
  #legend div label {
    font-size: 0.65em;
    display: block;
    float: left;
    width: 30px;
    text-align: center;
    box-sizing: border-box;
  }
  #legend div label:nth-child(1) {
    padding-left: 10px;
  }
  #info {
    top: 0;
    height: 100px;
    margin-top: 20px;
    width: 250px;
  }
</style>
</head>
<body>
<div id="map"></div>
<div class="overlay" id="info">
  <h2>US population density</h2>
  <div id="pd"><p>Hover over a state!</p></div>
</div>
<div id="legend" class="overlay">
  <h4>population density</h4>
  <div>
    <span style="background-color: #FFEDA0"></span>
    <span style="background-color: #FED976"></span>
    <span style="background-color: #FEB24C"></span>
    <span style="background-color: #FD8D3C"></span>
    <span style="background-color: #FC4E2A"></span>
    <span style="background-color: #E31A1C"></span>
    <span style="background-color: #BD0026"></span>
    <span style="background-color: #800026"></span>
  </div>
  <div class="labels">
    <label>0</label>
    <label>10</label>
    <label>20</label>
    <label>50</label>
    <label>100</label>
    <label>200</label>
    <label>500</label>
    <label>1000</label>
  </div>
</div>
<script>
    maptilersdk.config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE';
    var map = new maptilersdk.Map({
        container: 'map',
        style: maptilersdk.MapStyle.DATAVIZ.LIGHT,
        center: [-100.486052, 37.830348],
        zoom: 3
    });
    var hoveredStateId = null;

    map.on('load', function () {
        map.addSource('states', {
            'type': 'geojson',
            'data':
                'https://docs.maptiler.com/sdk-js/assets/us_states.geojson'
        });

        // The feature-state dependent fill-opacity expression will render the hover effect
        // when a feature's hover state is set to true.
        map.addLayer({
            'id': 'state-fills',
            'type': 'fill',
            'source': 'states',
            'layout': {},
            'paint': {
                'fill-color': ["step",
                    ["get", "DENSITY"],
                    "#FFEDA0", 10,
                    "#FED976", 20,
                    "#FEB24C", 50,
                    "#FD8D3C", 100,
                    "#FC4E2A", 200,
                    "#E31A1C", 500,
                    "#BD0026", 1000,
                    "#800026"
                ],
                'fill-opacity': [
                    'case',
                    ['boolean', ['feature-state', 'hover'], false],
                    1,
                    0.8
                ],
                'fill-outline-color': "rgba(255, 255, 255, 0)"
            }
        });

        map.addLayer({
            'id': 'state-borders',
            'type': 'line',
            'source': 'states',
            'layout': {},
            'paint': {
                'line-color': '#FFFFFF',
                'line-width': [
                    'case',
                    ['boolean', ['feature-state', 'hover'], false],
                    3,
                    1
                ],
            }
        });

        // When the user moves their mouse over the state-fill layer, we'll update the
        // feature state for the feature under the mouse.
        map.on('mousemove', 'state-fills', function (e) {
            if (e.features.length > 0) {
                if (hoveredStateId) {
                    map.setFeatureState(
                        { source: 'states', id: hoveredStateId },
                        { hover: false }
                    );
                }
                hoveredStateId = e.features[0].id;
                map.setFeatureState(
                    { source: 'states', id: hoveredStateId },
                    { hover: true }
                );
            }
            document.getElementById('pd').innerHTML = `<h3>${e.features[0].properties.STATE_NAME}</h3>
            <p><strong><em>${e.features[0].properties.DENSITY}</strong> people per square mile</em></p>`;
        });

        // When the mouse leaves the state-fill layer, update the feature state of the
        // previously hovered feature.
        map.on('mouseleave', 'state-fills', function () {
            if (hoveredStateId) {
                map.setFeatureState(
                    { source: 'states', id: hoveredStateId },
                    { hover: false }
                );
            }
            hoveredStateId = null;
            document.getElementById('pd').innerHTML = `<p>Hover over a state!</p>`;
        });
    });
</script>
</body>
</html>
HTML
An extension of MapLibre GL JS