Documentation menu
Example
Choropleth
Polygons coloured by a number on each one, with a graduated ramp you can read at a glance and white outlines that keep neighbouring areas apart. The same pattern fits wards, postcode districts, sales territories or delivery zones.
ts
import { createMap, DataLayer } from "@mapmap/maps";
const map = createMap({
container: "map",
apiKey: "snk_...",
attributionPosition: "bottom-left",
center: [-0.12, 51.5],
zoom: 10.3,
});
await map.whenReady();
// Sample data: a grid of cells over London, each with a value. Your own
// polygons work the same: data: "https://cdn.example.com/wards.geojson".
const cells: GeoJSON.Feature[] = [];
for (let x = 0; x < 18; x++) {
for (let y = 0; y < 12; y++) {
const west = -0.42 + x * 0.034, south = 51.36 + y * 0.025;
const d = Math.hypot(x - 9, (y - 6) * 1.4);
cells.push({
type: "Feature",
properties: { cell: x * 100 + y, value: Math.round(9000 / (1 + d * d * 0.3)) },
geometry: {
type: "Polygon",
coordinates: [[
[west, south], [west + 0.034, south], [west + 0.034, south + 0.025],
[west, south + 0.025], [west, south],
]],
},
});
}
}
// A fill and an outline at slot "middle", coloured along the stops.
new DataLayer(map, {
data: { type: "FeatureCollection", features: cells },
promoteId: "cell",
style: {
simple: { opacity: 0.7, width: 0.6, outlineColor: "#ffffff" },
graduated: {
property: "value",
stops: [
[0, "#eff3ff"],
[1000, "#bdd7e7"],
[3000, "#6baed6"],
[6000, "#3182bd"],
[9000, "#08519c"],
],
},
},
popup: (f) => {
const el = document.createElement("div");
el.textContent = "Value " + String(f.properties?.value); // text, never HTML
return el;
},
});Worth knowing
- graduated blends linearly between the stops, which must be strictly ascending (DataLayer throws on stops that are not). For hard classes, draw the layer yourself with map.addPersistentLayer and a step expression.
- Keep the value you colour on as a top-level number in properties. MapLibre reads nested objects as JSON strings, so properties.stats.value cannot be styled on.
- Hover and click highlights are on by default (feature-state, so no setData). promoteId names a unique property so the highlight lands on one cell.