Visualize Multigraph with Deck.gl
Multigraph’s power comes from it’s ability to return multiple geometry types. The base-level is nodes - here we’re using the raw nodes to manually aggregate into dynamic hexagons
<!DOCTYPE html>
<html>
<head>
    <!--  Include mapboxgl javascript and css -->
    <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.6.0/mapbox-gl.js"></script>
    <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.6.0/mapbox-gl.css" rel="stylesheet">
    <!-- Include deck.gl -->
    <script src="https://unpkg.com/deck.gl@latest/dist.min.js"></script>
    <script type="text/javascript">
        const { MapboxLayer, HexagonLayer } = deck;
    </script>
    <!--  Include targomo core -->
    <script src="https://releases.targomo.com/core/latest.min.js"></script>
    <!--  Include micro progress bar  -->
    <script src="https://www.targomo.com/developers/scripts/mipb.min.js"></script>
    <style>
        body, html {
            margin: 0;
            width: 100%;
            height: 100%;
        }
        #control-panel {
            position: absolute;
            margin: 10px;
            font-family: 'Open Sans', sans-serif;
            top: 0; z-index: 100;
            display: flex;
            flex-direction: column;
            padding: 5px 8px;
            background: #fff;
        }
        .panel-item {
            display: flex;
            align-items: center;
            justify-content: space-between;
        }
        #map {
            width: 100%;
            height: 100%;
        }
    </style>
</head>
<body>
    <!--  where the map will live  -->
    <div id="map"></div>
    <div id="control-panel">
        <div class="panel-item">
            <label>Hex size</label>
            <input id="radius" type="range" min="100" max="500" step="50" value="200"></input>
            <span id="radius-value"></span>
        </div>
        <div class="panel-item">
            <label>Hex pct.</label>
            <input id="coverage" type="range" min="0" max="1" step="0.1" value=".9"></input>
            <span id="coverage-value"></span>
        </div>
    </div>
    <script>
        // create targomo client
        const client = new tgm.TargomoClient('westcentraleurope', '__targomo_key_here__');
        // Coordinates to center the map
        const source = { id: "src", lng: 2.375, lat: 48.844 };
        const attributionText = `<a href="https://www.targomo.com/developers/resources/attribution/" target="_blank">&copy; Targomo</a>`;;
        
        // set the progress bar
        const pBar = new mipb({ fg: "#FF8319" });
        
        // add the map and set the initial center to berlin
        const map = new mapboxgl.Map({
            container: 'map',
            style: 'https://api.maptiler.com/maps/positron/style.json?key=__your_maptiler_api_key__',
            zoom: 11, pitch: 40,
            center: source,
            attributionControl: false
        })
            .addControl(new mapboxgl.NavigationControl())
            .addControl(new mapboxgl.AttributionControl({ compact: true, customAttribution: attributionText }));
        
        // disable scroll zoom
        map.scrollZoom.disable();
        
        
        const marker = new mapboxgl.Marker({
            //draggable: true
        }).setLngLat(source).addTo(map);
        // container for housing the multigraph data
        let data = [];
        
        const OPTIONS = ["radius", "coverage"];
        
        const COLOR_RANGE = [
            [26, 152, 80], [145, 207, 96],
            [217, 239, 139], [254, 224, 139],
            [252, 141, 89], [215, 48, 39]
        ];
        
        function renderLayer() {
            const options = {};
            OPTIONS.forEach((key) => {
                const value = +document.getElementById(key).value;
                document.getElementById(key + "-value").innerHTML = value;
                options[key] = value;
            });
        
            const myDeckLayer = new MapboxLayer({
                id: 'heatmap',
                type: HexagonLayer,
                colorRange: COLOR_RANGE,
                data,
                getPosition: (d) => [Number(d.lng), Number(d.lat)],
                getColorWeight: (d) => d.w,
                colorAggregation: "MEAN",
                opacity: 0.3,
                ...options
            });
        
            if (map.getLayer('heatmap')) {
                map.removeLayer('heatmap')
            }
            map.addLayer(myDeckLayer, "place_other");
        }
        
        async function setUp() {
            // show progress bar
            pBar.show();
            // here we're deciding that we want transit coverage, 30 minutes (1800s), nodes (as we are aggregating with deckGL)
            const multigraphOptions = {
                edgeWeight: "time",
                travelType: "transit",
                maxEdgeWeight: 1800,
                multigraph: {
                    layer: { type: "identity" },
                    domain: { type: "node" },
                    serialization: { format: "geojson" },
                    aggregation: { type: "routing_union" }
                }
            };
        
            const mg = await client.multigraph.fetch([source], multigraphOptions);
        
            // hide progress bar
            pBar.hide()
        
            data = mg.data.features.map((f) => {
                return {
                    lng: f.geometry.coordinates[0],
                    lat: f.geometry.coordinates[1],
                    w: f.properties.w
                };
            });
        
            // initial layer rendering
            renderLayer();
        
            OPTIONS.forEach((key) => {
                // re-render when hex settings change
                document.getElementById(key).oninput = renderLayer;
            });
        }
        
        map.on('load', () => {
            setUp();
        });
    </script>
</body>
</html>
content_copy
Copied to clipboard