Maplibre-GL Tiled Multigraph
People will walk 15 minutes to go to a coffee shop - where are the areas in San Francisco which are not within 15 minutes of a coffee shop?
<!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 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%;
}
#map {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<!-- where the map will live -->
<div id="map"></div>
<script>
// create targomo client
const client = new tgm.TargomoClient('northamerica', '__targomo_key_here__')
// Coordinates to center the map
const lnglat = [-122.45, 37.774]
// set the progress bar
const pBar = new mipb({ fg: "#FF8319" })
pBar.show()
// add the map and set the initial center to berlin
const map = new maplibregl.Map({
container: 'map',
style: client.basemaps.getGLStyleURL("Light"),
zoom: 12,
center: lnglat
}).addControl(new maplibregl.NavigationControl())
// disable scroll zoom
map.scrollZoom.disable()
// here we're deciding that we want walk coverage, 15 minutes (900s), symbolized as hexagons
const multigraphOptions = {
edgeWeight: "time",
travelType: "walk",
maxEdgeWeight: 900,
multigraph: {
aggregation: {
type: "routing_union"
},
layer: {
type: "hexagon"
},
serialization: {
format: "mvt"
}
}
}
map.on("load", async () => {
const dataurl = 'https://raw.githubusercontent.com/targomo/data-exports/master/overpass/cuisine_coffee_shop_san_francisco.geojson'
// get OSM coffee shop dataset
const coffeeShops = await fetch(dataurl).then(async (data) => {
return JSON.parse(await data.text())
})
// add coffee shops to map
map.addLayer({
id: "coffee",
type: "circle",
paint: {
"circle-radius": 3,
"circle-color": "#666"
},
source: {
type: "geojson",
data: coffeeShops,
attribution: '<a href="https://www.targomo.com/developers/resources/attribution/" target="_blank">© Targomo</a>'
}
})
// create formatted 'sources' for analysis
const sources = coffeeShops.features.map((coffee) => {
return {
id: coffee.properties['@id'],
lat: coffee.geometry.coordinates[1],
lng: coffee.geometry.coordinates[0]
}
})
// get the MVT tile url for the multigraph tiles
const mgUrl = await client.multigraph.getTiledMultigraphUrl(
sources, multigraphOptions, "mvt"
)
// add the tiled multigraph
map.addLayer({
id: "multigraph",
type: "fill",
source: {
type: "vector",
tiles: [ mgUrl ],
minzoom: 6,
maxzoom: 20
},
"source-layer": "aggregation",
layout: {},
paint: { // symbolize hexagons on a Green-Yellow-Red interpolated scale
"fill-opacity": 0.6,
"fill-outline-color": "rgba(255,255,255,0.15)",
"fill-color": [
"interpolate-hcl",
["linear"],
["get", "w"], // "w" is the "edgeWeight", which in this case is time
0, "#1a9641", 450, "#ffffbf", 900, "#d7191c"
]
}
}, "coffee")
pBar.hide()
// Change the cursor to a pointer when the mouse is over the hex layer
map.on("mouseenter", "multigraph", function() {
map.getCanvas().style.cursor = "pointer"
})
// Change it back to a pointer when it leaves.
map.on("mouseleave", "multigraph", function() {
map.getCanvas().style.cursor = ""
})
map.on("click", "multigraph", function(e) {
var description = `${Math.round(
e.features[0].properties.w / 60
)} minute walk<br>to closest coffee shop`
new maplibregl.Popup()
.setLngLat(e.lngLat)
.setHTML(description)
.addTo(map)
})
})
</script>
</body>
</html>
Copied to clipboard