Maplibre-GL Planning Multi-stop Scenarios
What’s the most efficient way to bike to Seattle’s central brewpubs?
<!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 turf for geographic analysis -->
<script src="https://npmcdn.com/@turf/turf/turf.min.js"></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%;
}
#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__')
// set the progress bar
const pBar = new mipb({ fg: '#FF8319' })
// Coordinates to center the map
const microbreweries = [
[47.65924, -122.36559, 'Hale\'s Ales Brewery'],
[47.64906, -122.34445, 'Fremont Brewing'],
[47.65786, -122.31356, 'Big Time Brewery'],
[47.66823, -122.29916, 'Ravenna Brewing Company'],
[47.66150, -122.31981, 'Floating Bridge Brewing'],
[47.66666, -122.37252, 'Obec Brewing'],
[47.61161, -122.34527, 'Cloudburst Brewing'],
[47.61429, -122.34567, 'Belltown Brewing'],
[47.60949, -122.34285, 'Old Stove Brewing'],
[47.6519, -122.35399, 'Aslan Brewing']
]
const targets = turf.featureCollection(
microbreweries.map(m =>
turf.point(m.slice(0, 2).reverse(), { name: m[2] })
)
)
const center = turf.center(targets)
const start = [-122.34964, 47.62145]
// generate 15 random delivery locations
targets.features.forEach((f, i) => f.properties.id = 'delivery' + (i + 1))
// add the map and set the initial center
const map = new maplibregl.Map({
container: 'map',
style: client.basemaps.getGLStyleURL('Light'),
zoom: 10,
pitch: 30,
center: center.geometry.coordinates
}).addControl(new maplibregl.NavigationControl())
// disable scroll zoom
map.scrollZoom.disable()
// zoom to limits of target points
map.fitBounds(turf.bbox(targets), { padding: 20 })
// add draggable source
const marker = new maplibregl.Marker({
draggable: true
}).setLngLat(start).addTo(map)
// react to marker move
marker.on('dragend', getRoute)
async function getRoute() {
// show progress bar
pBar.show()
const routingConfig = {
optimizationAlgorithm: 'GREEDY_TSP',
stores: [{
uuid: 'depot1',
address: marker.getLngLat()
}],
orders: targets.features.map((f) => {
return {
uuid: f.properties.id,
storeUuid: 'depot1',
address: {
lat: f.geometry.coordinates[1],
lng: f.geometry.coordinates[0],
avgHandlingTime: 250
}
}
}),
transports: [{
vehicle: {
uuid: 'v1',
storeUuid: 'depot1'
}
}],
optimizationMetadata: {
geojsonCreation: 'ROUTING_SERVICE',
travelOptions: {
travelType: 'bike',
maxEdgeWeight: 7200,
serviceUrl: 'https://api.targomo.com/northamerica/',
serviceKey: client.serviceKey
}
}
}
const url = `https://api.targomo.com/fleetplanner/v1/api/key-auth/optimizations?key=${client.serviceKey}`
try {
const data = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(routingConfig)
})
const routingResults = await data.json()
map.getSource('routes').setData(routingResults.tours[0].featureCollection)
// hide progress bar
pBar.hide()
} catch (error) {
console.error(error)
}
}
map.on('load', () => {
map.addSource('targets', {
type: 'geojson',
data: targets
})
map.addLayer({
id: 'targetsLayer',
type: 'circle',
source: 'targets',
paint: {
'circle-radius': 8,
'circle-color': '#ff7800'
}
})
map.addSource('routes', {
type: 'geojson',
data: turf.featureCollection([]),
attribution: '<a href="https://www.targomo.com/developers/resources/attribution/" target="_blank">© Targomo</a>'
})
map.addLayer({
id: 'routesLayer',
type: 'line',
source: 'routes',
layout: {
'line-join': 'round',
'line-cap': 'round'
},
paint: {
'line-color': '#00242B',
'line-width': 5
},
filter: ['==', '$type', 'LineString']
}, 'targetsLayer')
getRoute()
})
</script></body>
</html>
Copied to clipboard