Skip to content

Instantly share code, notes, and snippets.

@rfriberg
Created January 13, 2017 23:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rfriberg/92fb1b7d644b868bf9914b8f473fbbdf to your computer and use it in GitHub Desktop.
Save rfriberg/92fb1b7d644b868bf9914b8f473fbbdf to your computer and use it in GitHub Desktop.
Travel by Map - work in progress
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Travel by Map Example (WIP)</title>
<link rel="stylesheet" href="https://mapzen.com/js/mapzen.css"/>
<link rel="stylesheet" href="https://unpkg.com/leaflet-easybutton@2.0.0/src/easy-button.css">
<link rel="stylesheet" href="https://unpkg.com/lrm-mapzen/dist/lrm-mapzen.css" />
<style>
.icon {
font-size: 20px;
}
.icon-mode {
font-size: 40px;
position: absolute;
z-index: 1000;
top: 48%;
left: 49%;
visibility: hidden;
}
.leaflet-routing-container {
display: none;
}
</style>
<script src="https://mapzen.com/js/mapzen.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-routing-machine/3.2.4/leaflet-routing-machine.min.js"></script>
<script src="https://unpkg.com/leaflet-easybutton@2.0.0/src/easy-button.js"></script>
<script src="https://unpkg.com/lrm-mapzen/dist/lrm-mapzen.js"></script>
<script src="https://npmcdn.com/@turf/turf@3.5.1/turf.js"></script>
</head>
<body>
<div id="map"></div>
<div class="icon-mode" id="pedestrian">🏃</div>
<div class="icon-mode" id="bird">✈️️</div>
<div class="icon-mode" id="auto">🚗</div>
<div class="icon-mode" id="bicycle">🚲</div>
<script>
// TODO:
// - Hide line (optionally)
// - Add hash
// - Base zoom level on total distance (and mode)
// - Re-run route based on new costing level for each mode
var map = L.Mapzen.map('map', {
scene: L.Mapzen.BasemapStyles.RefillMoreLabels,
debugTangram: true
});
var la = L.latLng(33.8128,-117.9259),
chicago = L.latLng(41.8758,-87.6189),
vistapoint = L.latLng(37.839682,-122.485284),
fairyland = L.latLng(37.809270,-122.259810);
var currentRoute = [],
currentTimeouts = [],
currentRouteBounds,
firstAndLast,
currentIcon,
zoom, speed,
tangramLayer;
var modeConfig = {
auto: {
zoom: 18,
speed: 120
},
bicycle: {
zoom: 18,
speed: 40
},
pedestrian: {
zoom: 20,
speed: 10
},
bird: {
zoom: 12,
speed: 1200
}
};
var demo = {
costing: 'auto' // auto, bicycle, pedestrian, multimodal
};
var control = L.Routing.control({
routeLine: function (route, options) {
// Update currentRoute
currentRoute = route;
console.log('This is where you can get info about the current route')
// Update first and last route points
var lastIndex = currentRoute.coordinates.length - 1;
firstAndLast = [currentRoute.coordinates[0], currentRoute.coordinates[lastIndex]];
return L.Routing.mapzenLine(route, options);
},
lineOptions: {
styles: [{ color: '#f66', opacity: 0.8, weight: 5 }]
},
waypoints: [
vistapoint,
fairyland
],
geocoder: L.Mapzen.geocoder('mapzen-JA21Wes'),
router: L.Routing.mapzen('mapzen-JA21Wes', demo),
formatter: new L.Routing.mapzenFormatter(),
summaryTemplate:'<div class="start">{name}</div><div class="info {costing}">{distance}, {time}</div>'
}).addTo(map);
// Not showing control right now
control.hide();
L.Routing.errorControl(control).addTo(map);
// Update route bounds anytime new route is selected
control.on('routeselected', function(r) {
var line = L.Routing.line(r.route)
currentRouteBounds = line.getBounds();
});
map.on('tangramloaded', function (e) {
tangramLayer = e.tangramLayer;
addButtons();
});
function addButtons() {
L.easyButton('<span class="icon pedestrian" title="Take a stroll">🏃‍♀️</span>', function(){
console.log("******** TO DO **********")
// TODO: rerun route with different costing mode
beginAdventure('pedestrian');
}).addTo(map);
L.easyButton('<span class="icon bicycle" title="Let\'s ride bikes">🚲</span>', function(){
beginAdventure('bicycle');
}).addTo(map);
L.easyButton('<span class="icon auto" title="We be driving">🚗</span>', function(){
beginAdventure('auto');
}).addTo(map);
L.easyButton('<span class="icon bird" title="Fly!">✈</span>', function(){
beginAdventure('bird');
}).addTo(map);
L.easyButton( '<span class="icon stop" title="Stop the madness!">🙀</span>', function(){
endAdventure();
}).addTo(map);
}
function beginAdventure(mode) {
if (currentTimeouts.length > 0) {
endAdventure();
}
zoom = modeConfig[mode].zoom;
speed = modeConfig[mode].speed;
currentIcon = mode;
var route = currentRoute;
if (mode == 'bird') {
// Use current zoom if that's closer
// TODO: link zoom level to total distance of route
var currentZoom = map.getZoom();
if (currentZoom > zoom) zoom = currentZoom;
route = {coordinates: firstAndLast};
}
travelByMap(route);
}
function endAdventure() {
// Clear pending timeouts
for (var x = 0; x < currentTimeouts.length; x++) {
clearTimeout(currentTimeouts[x]);
}
currentTimeouts = [];
// Hide emoji
hideEmojis();
// Back to original view
if (currentRouteBounds) map.fitBounds(currentRouteBounds);
}
function travelByMap(route) {
var routeCoords = route.coordinates;
// Zoom in on first coordinate
map.setView(routeCoords[0], zoom);
// Display appropriate emoji
document.getElementById(currentIcon).style.visibility = "visible";
// Pause 2 seconds before initiating to let people get their bearings
var routeCoords = route.coordinates;
setTimeout(initiateTravel, 2000, routeCoords);
}
function initiateTravel(routeCoords) {
var loopTime = 0;
for (var x = 0; x < routeCoords.length; x++) {
var thisCoord = routeCoords[x],
nextCoord = routeCoords[x + 1] ? routeCoords[x + 1] : null,
units = 'miles';
var distance = nextCoord ? turf.distance(getGeoJSONPoint(thisCoord), getGeoJSONPoint(nextCoord), units) : 0.001;
var durationTime = distance * 3600 / speed; // in seconds // distance (mi) * (seconds to hours conv) / speed (mph)
// Rounding to avoid extra micro times in loopTime
//durationTime = Math.round(durationTime * 100) / 100;
if (nextCoord && distance > 0) {
var timeout = setTimeout(function(y) {
map.panTo(y.coord, {animate: true, duration: y.time, easeLinearity: 1, noMoveStart: true});
}, loopTime, {coord: nextCoord, time: durationTime});
currentTimeouts.push(timeout);
}
// Set loopTime for next point
loopTime += (durationTime * 1000); // in miliseconds
}
}
// Intercept keypress to change basemap
document.onkeydown = function(evt) {
if (!tangramLayer) return;
evt = evt || window.event;
var basemap;
switch(evt.key) {
case 'r':
basemap = L.Mapzen.BasemapStyles.RefillMoreLabels;
break;
case 't':
basemap = L.Mapzen.BasemapStyles.TronMoreLabels;
break;
case 'w':
basemap = L.Mapzen.BasemapStyles.WalkaboutMoreLabels;
break;
case 'b':
basemap = L.Mapzen.BasemapStyles.BubbleWrap;
break;
default:
// do nothing
return;
}
// Update basemap
tangramLayer.scene.load(basemap);
};
/* HELPERS */
function hideEmojis() {
var elements = document.getElementsByClassName('icon-mode');
for (var x = 0; x < elements.length; x ++) {
elements[x].style.visibility = "hidden";
}
}
function getGeoJSONPoint(coord) {
return {
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'Point',
'coordinates': [coord.lat, coord.lng]
}
};
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment