Skip to content

Distance matrix

This example calculates the distance and travel time from one start point to several destinations at once — useful for finding the nearest of several locations (e.g. the closest available driver or store). Click the map to set the start point, then click one or more destinations; each one is calculated and listed as soon as you place it.

<!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;
                display: flex;
            }

            #map {
                flex: 1;
                height: 100vh;
            }

            #panel {
                width: 260px;
                height: 100vh;
                background-color: rgba(255, 255, 255, 0.9);
                padding: 10px;
                font: 13px sans-serif;
                box-sizing: border-box;
                overflow-y: auto;
            }

            #reset-button {
                display: block;
                margin-top: 10px;
                background-color: #18345c;
                color: white;
                border: none;
                padding: 8px 14px;
                cursor: pointer;
                border-radius: 4px;
            }

            #results div {
                margin-top: 8px;
                padding-top: 8px;
                border-top: 1px solid rgba(0, 0, 0, 0.1);
            }

            .marker-number {
                background: #0a5fa0;
                color: #fff;
                width: 22px;
                height: 22px;
                border-radius: 50%;
                display: flex;
                align-items: center;
                justify-content: center;
                font: 700 12px sans-serif;
                border: 2px solid #fff;
                box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
            }
        </style>
    </head>

    <body>
        <div id="panel">
            <strong>Click the map to set the start point, then click one or more destinations.</strong>
            <div id="results"></div>
            <button id="reset-button">Reset</button>
        </div>

        <div id="map"></div>

        <script>
            const map = new smartmapsgl.Map({
                apiKey: '[INSERT API-KEY]',
                container: 'map',
                center: { lat: 49.02164948779226, lng: 8.439330018049352 },
                zoom: 11,
                style: smartmapsgl.MapStyle.LIGHT
            });

            const resultsEl = document.getElementById('results');

            let startPoint = null;
            let destinations = [];
            let markers = [];

            function numberedMarker(n) {
                const el = document.createElement('div');
                el.className = 'marker-number';
                el.textContent = n;
                return new smartmapsgl.Marker({ element: el });
            }

            function reset() {
                startPoint = null;
                destinations = [];
                markers.forEach((marker) => marker.remove());
                markers = [];
                resultsEl.innerHTML = '';
            }

            document.getElementById('reset-button').addEventListener('click', reset);

            async function calculateMatrix() {
                resultsEl.innerHTML = 'Calculating…';

                try {
                    const response = await fetch(
                        'https://www.yellowmap.de/api_rst/v2/geojson/route?apiKey=[INSERT API-KEY]',
                        {
                            method: 'POST',
                            headers: { 'Content-Type': 'application/json' },
                            body: JSON.stringify({
                                type: 'FeatureCollection',
                                routingparams: {
                                    type: 'MATRIX',
                                    coordFormatOut: 'GEODECIMAL_POINT',
                                    speedProfile: 'FAST',
                                    routingTimeMode: 'ARRIVAL'
                                },
                                authentication: { channel: '' },
                                crs: { type: 'name', properties: { name: 'urn:ogc:def:crs:OGC:1.3:CRS84' } },
                                features: [
                                    {
                                        type: 'Feature',
                                        geometry: { type: 'Point', coordinates: [startPoint.lng, startPoint.lat] },
                                        properties: { type: 'StartPoint' }
                                    },
                                    {
                                        type: 'Feature',
                                        geometry: {
                                            type: 'MultiPoint',
                                            coordinates: destinations.map((d) => [d.lng, d.lat])
                                        },
                                        properties: {}
                                    }
                                ]
                            })
                        }
                    );

                    if (!response.ok) throw new Error(`Server error: ${response.status}`);

                    const result = await response.json();
                    // The start point comes back as a single feature; the distance
                    // and time to each destination are listed in the SAME order as
                    // the destination MultiPoint coordinates were sent.
                    const legs = result.features[0].properties.routingDestinations;

                    resultsEl.innerHTML = legs
                        .map((leg, i) => {
                            const km = (leg.distanceInMeters / 1000).toFixed(1);
                            const min = Math.round(leg.timeInSeconds / 60);
                            return `<div><strong>Destination ${i + 1}:</strong> ${km} km, ${min} min</div>`;
                        })
                        .join('');
                } catch (error) {
                    console.error('Error fetching matrix:', error);
                    resultsEl.innerHTML = 'Failed to calculate the matrix. Please try again.';
                }
            }

            map.on('click', (event) => {
                const point = { lng: event.lngLat.lng, lat: event.lngLat.lat };

                if (!startPoint) {
                    startPoint = point;
                    markers.push(new smartmapsgl.Marker({ color: '#18345c' }).setLngLat(event.lngLat).addTo(map));
                    resultsEl.innerHTML = 'Now click one or more destinations.';
                    return;
                }

                destinations.push(point);
                markers.push(numberedMarker(destinations.length).setLngLat(event.lngLat).addTo(map));
                calculateMatrix();
            });
        </script>
    </body>
</html>

Notes

  • The start point and the destinations are two separate GeoJSON features — a Point with properties.type: "StartPoint", and a MultiPoint collecting every destination.
  • The response contains one feature for the start point; its properties.routingDestinations array holds { distanceInMeters, timeInSeconds } for each destination, in the same order the destination coordinates were sent in. Nothing in the response repeats which coordinate a given entry belongs to — you have to track that order yourself, as this example does with the destinations array.

See the Matrix reference for the full parameter list, or the library version if you'd rather call it from the @smartmaps/routing npm package. Route Optimization shows a distance matrix combined with Isochrone and Autocomplete in a full logistics scenario.