Choropleth Map
Visualize data on a map by coloring polygons based on property values using data-driven fill-color expressions.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.smartmaps.cloud/packages/smartmaps/smartmaps-gl/v2/umd/smartmaps-gl.min.js"></script>
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; }
#legend {
position: absolute;
bottom: 30px;
right: 20px;
background: white;
padding: 12px 16px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.15);
font-family: sans-serif;
font-size: 13px;
z-index: 1;
}
#legend h4 { margin: 0 0 8px 0; color: #18345c; }
.legend-item { display: flex; align-items: center; gap: 8px; margin: 4px 0; }
.legend-color { width: 16px; height: 16px; border-radius: 3px; border: 1px solid rgba(0,0,0,0.2); }
</style>
</head>
<body>
<div id="map"></div>
<div id="legend">
<h4>Density (per km²)</h4>
<div class="legend-item"><span class="legend-color" style="background:#ffffcc"></span> < 200</div>
<div class="legend-item"><span class="legend-color" style="background:#a1dab4"></span> 200 – 500</div>
<div class="legend-item"><span class="legend-color" style="background:#41b6c4"></span> 500 – 1000</div>
<div class="legend-item"><span class="legend-color" style="background:#225ea8"></span> > 1000</div>
</div>
<script>
const map = new smartmapsgl.Map({
apiKey: "[INSERT API-KEY]",
container: "map",
center: { lat: 48.78, lng: 9.18 },
zoom: 10,
style: smartmapsgl.MapStyle.LIGHT
});
// Stuttgart districts as GeoJSON polygons with population density
const districts = {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: { name: "Stuttgart-Mitte", density: 5200 },
geometry: {
type: "Polygon",
coordinates: [[
[9.165, 48.785], [9.190, 48.785], [9.195, 48.775],
[9.190, 48.765], [9.170, 48.765], [9.160, 48.775], [9.165, 48.785]
]]
}
},
{
type: "Feature",
properties: { name: "Bad Cannstatt", density: 3800 },
geometry: {
type: "Polygon",
coordinates: [[
[9.195, 48.810], [9.230, 48.810], [9.235, 48.795],
[9.220, 48.780], [9.195, 48.785], [9.190, 48.800], [9.195, 48.810]
]]
}
},
{
type: "Feature",
properties: { name: "Vaihingen", density: 1500 },
geometry: {
type: "Polygon",
coordinates: [[
[9.080, 48.745], [9.120, 48.750], [9.130, 48.740],
[9.125, 48.720], [9.095, 48.715], [9.075, 48.730], [9.080, 48.745]
]]
}
},
{
type: "Feature",
properties: { name: "Degerloch", density: 2200 },
geometry: {
type: "Polygon",
coordinates: [[
[9.160, 48.760], [9.190, 48.760], [9.195, 48.745],
[9.180, 48.735], [9.155, 48.738], [9.150, 48.750], [9.160, 48.760]
]]
}
},
{
type: "Feature",
properties: { name: "Feuerbach", density: 3200 },
geometry: {
type: "Polygon",
coordinates: [[
[9.140, 48.815], [9.170, 48.815], [9.175, 48.800],
[9.165, 48.790], [9.145, 48.790], [9.135, 48.800], [9.140, 48.815]
]]
}
},
{
type: "Feature",
properties: { name: "Plieningen", density: 650 },
geometry: {
type: "Polygon",
coordinates: [[
[9.190, 48.725], [9.225, 48.730], [9.230, 48.715],
[9.215, 48.700], [9.185, 48.700], [9.180, 48.715], [9.190, 48.725]
]]
}
},
{
type: "Feature",
properties: { name: "Möhringen", density: 180 },
geometry: {
type: "Polygon",
coordinates: [[
[9.130, 48.735], [9.155, 48.738], [9.165, 48.725],
[9.155, 48.710], [9.130, 48.710], [9.120, 48.720], [9.130, 48.735]
]]
}
}
]
};
map.on("load", () => {
map.addSource("districts", { type: "geojson", data: districts });
// Filled polygons with data-driven color
map.addLayer({
id: "district-fill",
type: "fill",
source: "districts",
paint: {
"fill-color": [
"interpolate", ["linear"], ["get", "density"],
0, "#ffffcc",
200, "#ffffcc",
500, "#a1dab4",
1000, "#41b6c4",
3000, "#225ea8"
],
"fill-opacity": 0.6
}
});
// Outline
map.addLayer({
id: "district-outline",
type: "line",
source: "districts",
paint: {
"line-color": "#18345c",
"line-width": 2
}
});
// Labels
map.addLayer({
id: "district-labels",
type: "symbol",
source: "districts",
layout: {
"text-field": ["get", "name"],
"text-size": 12,
"text-anchor": "center"
},
paint: {
"text-color": "#18345c",
"text-halo-color": "#ffffff",
"text-halo-width": 1.5
}
});
// Click popup with details
map.on("click", "district-fill", (e) => {
const props = e.features[0].properties;
new smartmapsgl.Popup()
.setLngLat(e.lngLat)
.setHTML(`<strong>${props.name}</strong><br>Density: ${props.density.toLocaleString()} / km²`)
.addTo(map);
});
map.on("mouseenter", "district-fill", () => {
map.getCanvas().style.cursor = "pointer";
});
map.on("mouseleave", "district-fill", () => {
map.getCanvas().style.cursor = "";
});
});
</script>
</body>
</html>