You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
safe-bike-routing/src/main.js

151 lines
4.8 KiB
JavaScript

import 'leaflet/dist/leaflet.css'
import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.webpack.css'
import 'leaflet-routing-machine/dist/leaflet-routing-machine.css'
import 'leaflet-defaulticon-compatibility'
import 'leaflet-sidebar-v2/css/leaflet-sidebar.min.css'
import './sidebar-router.css'
import L from 'leaflet'
import 'leaflet-routing-machine'
import 'leaflet-control-geocoder'
import 'leaflet-sidebar-v2'
import './L.Routing.OpenRouteService.v2.js'
const orsApi = '58d904a497c67e00015b45fca1cedc95775b47ecb9b0f391234b5ea8'
const router = L.Routing.openRouteService(orsApi)
const geocoder = L.Control.Geocoder.pelias(orsApi, { // ORS uses pelias for geocoding
serviceUrl: 'https://api.openrouteservice.org/geocode',
geocodingQueryParams: { 'boundary.country': 'DE' },
})
const map = L.map('map')
const basemaps = {
'Standard': L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors'
}),
'Fahrrad': L.tileLayer('https://tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=6c089d11787c4f32a3bff3d6f2ded175', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors'
}),
'ÖPNV': L.tileLayer('https://tile.thunderforest.com/transport/{z}/{x}/{y}.png?apikey=6c089d11787c4f32a3bff3d6f2ded175', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors'
}),
}
map.setView([52, 10], 6) // germany
// map.setView([52.52, 13.37], 12) // berlin
// map.setView([51.34, 12.38], 13) // leipzig
// map.setView([50.94, 6.96], 13) // cologne
basemaps['Standard'].addTo(map)
L.control.layers(basemaps, {}).addTo(map)
L.control.scale({ imperial: false, maxWidth: 300, }).addTo(map)
const routeCtrl = L.Routing.control({
position: 'topleft',
fitSelectedRoutes: false, // we do it ourselves to accomodate for the sidebar
router,
geocoder,
createMarker,
routeLine,
}).addTo(map)
document.querySelector('#routercontainer')
.appendChild(routeCtrl._container)
L.control.sidebar({ autopan: true })
.addTo(map)
.addPanel({
id: 'router',
tab: '<i class="fa fa-home"></i>',
pane: document.querySelector('#routingpanel'),
})
.addPanel({
id: 'gh',
tab: '<i class="fa fa-github"></i>',
button: 'https://git.nroo.de/norwin/safe-bike-routing',
})
.open('router')
addAvoidPolys('./gefaehrliche_kreuzungen_2019.json')
// ------ events --------
let lastRouteEvent = Date.now()
function updateLastRouteEvent () { lastRouteEvent = Date.now() }
routeCtrl.getPlan().on('waypointdrag', updateLastRouteEvent)
routeCtrl.on('routeselected', ({ route }) => {
// consider sidebar width when fitting a route
const offset = document.querySelector('.leaflet-sidebar-content').getBoundingClientRect().width;
const bounds = L.Routing.line(route).getBounds()
map.fitBounds(bounds, { paddingTopLeft: [40+offset, 0] });
})
map.on({
'load': setFocuspoint,
'movestart': setFocuspoint,
'click': addWaypoint,
})
function setFocuspoint () {
const { lat, lng } = map.getCenter()
geocoder.options.geocodingQueryParams['focus.point.lat'] = lat
geocoder.options.geocodingQueryParams['focus.point.lon'] = lng
}
function addWaypoint (event) {
// ignore clicks if a waypoint was dragged in the last second,
// as both events interfere with each other..
if (Date.now() - lastRouteEvent < 1000) return
const wp = routeCtrl.getWaypoints()
// // middle waypoint for > 2 waypoints does not properly stop click event, so we'd misbehave.
// if (wp.length > 2) return
const p = new L.Routing.Waypoint(event.latlng)
if (!wp[0].latLng) wp[0] = p
else if (!wp[1].latLng) wp[1] = p
else wp.push(p)
routeCtrl.setWaypoints(wp)
}
async function addAvoidPolys (url) {
const res = await fetch(url)
const avoid_polygons = await res.json()
router.options.orsOptions.options = { avoid_polygons }
L.geoJSON(avoid_polygons, {
style: () => ({ color: 'red', fillOpacity: 0.4 })
}).addTo(map)
return avoid_polygons
}
function createMarker (i, wp, n) {
// use default marker..
const m = L.Routing.Plan.prototype.options.createMarker(i, wp, n)
// but customize it:
m.once('contextmenu', () => routeCtrl.spliceWaypoints(i, 1))
// m.on('drag', () => updateLastRouteEvent)
let name = i == 0 ? 'Start' : i+1 == n ? 'Ziel' : ''
if (name) name = `<b>${name}</b>`
name = name && wp.name ? `${name}: ${wp.name}` : name || wp.name
if (name) m.bindTooltip(name, { permanent: i == 0 || i+1 == n })
return m
}
function routeLine (route) {
return L.Routing.Control.prototype.options.routeLine(route, {
styles: [
{color: 'black', opacity: 0.15, weight: 12},
{color: 'white', opacity: 0.8, weight: 7},
{color: '#00bb00', opacity: 1, weight: 4},
],
})
.on('linetouched', updateLastRouteEvent)
}