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">© 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>
Copied to clipboard