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>
content_copy
Copied to clipboard