GoogleMaps Tiled Multigraph
Deck.gl can allow us to put tiled layers onto GoogleMaps
<!DOCTYPE html>
<html>
<head>
    <!--  Include google maps api -->
    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&key=__your_google_api_key__" type="text/javascript"></script>
        <!--  Include targomo googlemaps full build -->
    <script src="https://releases.targomo.com/googlemaps/latest-full.min.js"></script>
    <!-- Include deck.gl -->
    <script src="https://unpkg.com/deck.gl@latest/dist.min.js"></script>
    <script type="text/javascript">
        const { MapboxLayer, MVTLayer } = deck;
    </script>
    <style>
        body, html {
            margin: 0; width: 100%; height: 100%;
            font-family: Helvetica, Arial, Sans-Serif;
        }
        #map {
            width: 100%;
            height: calc(100% - 15px);
        }
        #attribution {
            width: 100%; height: 15px;
            background-color: #04343f;
            display: flex;
            justify-content: end;
            align-items: center;
        }
        #attribution > a {
            font-size: 9px;
            padding-right: 5px;
            color: #ffffffa8;
            text-decoration: none;
        }
        #tooltip {
            background-color: #04343f;
            color: #ffffffa8;;
            font-size: 9px;
            padding: 5px;
            border-radius: 4px;
            display: none;
        }
        #select-container {
            position: absolute; font-size: 11px;
            top: 0px; right: 0px;
            padding: 5px; z-index: 400;
            background-color: white;
        }
        #select-container > input[type=radio] {
            height: 11px;
        }
    </style>
</head><body>
    <!--  where the map will live  -->
    <div id="map"></div>
    <!--  checkbox used to change the mutigraph mode  -->
    <div id="select-container">
        <input type="radio" id="hex" name="mode" value="hex" onchange="setLayer('hexagon')" checked>
        <label for="hex">Hexagons</label>
        <input type="radio" id="line" name="mode" value="line" onchange="setLayer('line')">
        <label for="line">Lines</label>
    </div>
    <div id="tooltip" style="position: absolute; z-index: 1; pointer-events: none;"></div>
    <div id="attribution"><a href='https://targomo.com/developers/resources/attribution/' target='_blank'>&copy; Targomo</a> <a href='https://www.openstreetmap.org/copyright' target='_blank'>&copy; OpenStreetMap contributors</a></div>
    <script>
        // create targomo client
        const client = new tgm.TargomoClient('northamerica', '__targomo_key_here__');
        
        const sources = [{ id: 1, lat: 40.733831, lng: -74.002154 }, { id: 2, lat: 40.809765, lng: -73.950152 }];
        
        // define the map
        const map = new google.maps.Map(document.getElementById("map"), {
            zoom: 12, disableDefaultUI: true, zoomControl: true,
            center: { lat: (sources[0].lat + sources[1].lat) / 2, lng: (sources[0].lng + sources[1].lng) / 2 },
        });
        
        var mapType = new google.maps.StyledMapType([{
            featureType: "all", elementType: "all",
            clickableIcons: false, draggableCursor:'',stylers: [ { saturation: -100 } ]}
        ], { name:"Grayscale" });    
        map.mapTypes.set('grayscale', mapType);
        map.setMapTypeId('grayscale');
        
        sources.forEach(source => {
            const myLatlng = new google.maps.LatLng(source.lat, source.lng);
            const marker = new google.maps.Marker({
                position: myLatlng,
                map: map
            });
        });
        
        const deckOverlay = new deck.GoogleMapsOverlay({
            layers: []
        });
        
        async function setLayer(mode){
            const multigraphOptions = {
                edgeWeight: "time",
                useClientCache: true,
                travelType: "transit",
                maxEdgeWeight: 1800,
                multigraph: {
                    aggregation: {
                        type: 'routing_union'
                    },
                    layer: {
                        geometryDetailPerTile: 5,
                        minGeometryDetailLevel: 5,
                        maxGeometryDetailLevel: 25,
                        type: mode === "hexagon" ? "hexagon" : "identity"
                    },
                    serialization: {
                        format: "mvt",
                    },
                    domain: {
                        type: "edge"
                    }
                }
            }
        
            // get the MVT tile url for the multigraph tiles
            const mgUrl = await client.multigraph.getTiledMultigraphUrl(
                sources, multigraphOptions, "mvt"
            );
        
            const colors = [
                [26, 152, 80], [145, 207, 96], [217, 239, 139],
                [254, 224, 139], [252, 141, 89], [215, 48, 39]
            ];
        
            const layer = new MVTLayer({
                data: mgUrl,
                pickable: true, 
                stroked: false, 
                filled: true,
                minZoom: 0, maxZoom: 23,
                getLineWidth: 1,
                lineWidthMinPixels: 2,
                opacity: mode === "hexagon" ? .5 : 1,
                getFillColor: d => colors[Math.ceil((d.properties.w / 1800 * 6)) - 1],
                getLineColor: d => colors[Math.ceil((d.properties.w / 1800 * 6)) - 1],
                onHover: info => setTooltip(info.object, info.x, info.y)
            })
        
            deckOverlay.setProps({
                layers: [ layer ]
            });
        
            deckOverlay.setMap(map);
        }
        
        function setTooltip(object, x, y) {
            const el = document.getElementById('tooltip');
            if (object) {
                const travelTime = Math.ceil(object.properties.w / 60)
                el.innerHTML = `<strong>Travel Time:</strong> ${travelTime} minutes`;
                el.style.display = 'block'; el.style.left = x + 'px'; el.style.top = y + 'px';
            } else {
                el.style.display = 'none';
            }
        }
        
        setLayer('hexagon');
    </script>
</body>
</html>
content_copy
Copied to clipboard