Maplibre-GL Statistics Breakpoints
How to use Statistics Breakpoints to color a map.
<!DOCTYPE html>
<html>
<head>
<!-- Include maplibregl javascript and css -->
<script src="https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.js"></script>
<link href="https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.css" rel="stylesheet">
<!-- Include turf for geographic analysis -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js"></script>
<!-- Include targomo core -->
<script src="https://releases.targomo.com/core/latest.min.js"></script>
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head><body>
<!-- where the map will live -->
<div id="map"></div>
<script>
const apiKey = '__targomo_key_here__';
const collectionId = 100;
const statisticId = 0;
const region = "westcentraleurope"
const serviceUrl = "https://api.targomo.com/" + region
const map = new maplibregl.Map({
container: 'map',
style: 'https://maps.targomo.com/styles/positron-gl-style/style.json?key=' + apiKey,
zoom: 10,
center: [8.682091, 50.110642]
});
async function fetchMetaData(endpoint) {
try {
let url = new URL(endpoint);
url.searchParams.set("serviceUrl", serviceUrl)
url.searchParams.set("apiKey", apiKey)
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Request failed: ${response.body}`);
}
return response.json();
} catch (error) {
console.error(error.message);
}
}
function biggestArray(obj) {
let biggestArray = [];
for (const [key, value] of Object.entries(obj)) {
if (Array.isArray(value) && value.length > biggestArray.length) {
biggestArray = value;
}
}
return biggestArray;
}
async function generateLayerDefinition(collection, statistic) {
const collectionMeta = await fetchMetaData("https://api.targomo.com/statistics/collections/" + collection);
const groupMeta = await Promise.all(collectionMeta.statisticGroups.map((g) =>
fetchMetaData("https://api.targomo.com/statistics/meta/" + g.id)
));
// In the paint style the color definitions need to be sorted by ascending zoom level.
collectionMeta.statisticGroups.sort((a, b) => a.minZoom - b.minZoom);
const layerDef = {
"id": "targomo", // Layer ID
"type": "fill",
"source": {
"type": "vector",
"tiles": [`https://api.targomo.com/statistics/collections/tiles/${collection}/{z}/{x}/{y}.mvt?statistics=${statistic}&apiKey=${apiKey}&serviceUrl=` + encodeURI(serviceUrl)],
},
"source-layer": "statistics",
"paint": {
"fill-color": [
"step",
["zoom"],
],
"fill-opacity": 0.6
},
};
let paintSteps = layerDef.paint["fill-color"];
let first = true;
collectionMeta.statisticGroups.forEach((group) => {
if (first) {
first = false;
} else {
paintSteps.push(group.minZoom);
}
const kmeans = groupMeta.find((g) => g.id == group.id).stats.find((s) => s.statistic_id == statistic).breakpoints.kmeans;
const breakpoints = biggestArray(kmeans);
// steps from 0.0 to 1.0 to interpolate the colors
const steps = Array(breakpoints.length).keys().map((i) => i / (breakpoints.length - 1));
const colors = Array.from(steps.map(d3.interpolateYlOrRd));
const zipped = breakpoints.map((e, i) => [e, colors[i]]).flat();
paintSteps.push([
"interpolate-hcl",
["linear"],
["get", String(statistic)],
...zipped
]);
});
return layerDef;
}
let layerDefinition = generateLayerDefinition(collectionId, statisticId);
map.on('load', () => {
layerDefinition.then((def) => map.addLayer(def));
});
map.addControl(new maplibregl.NavigationControl());
</script>
</body>
</html>
Copied to clipboard