Created
December 1, 2015 03:06
-
-
Save geografa/217ee42b5ba6caa630c1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<meta charset=utf-8 /> | |
<title>Your nearest cup of coffee</title> | |
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /> | |
<script src='https://api.tiles.mapbox.com/mapbox.js/plugins/turf/v1.3.0/turf.min.js'></script> | |
<script src='https://api.tiles.mapbox.com/mapbox.js/v2.2.3/mapbox.js'></script> | |
<link href='https://api.tiles.mapbox.com/mapbox.js/v2.2.3/mapbox.css' rel='stylesheet' /> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> | |
<link href='https://www.mapbox.com/base/latest/base.css' rel='stylesheet' /> | |
<style> | |
body { margin:0; padding:0; } | |
path {pointer-events:none} | |
#map { position:absolute; top:51; bottom:0; width:100%; } | |
.leaflet-popup-content .marker-title{font-weight:400;color:#999;line-height:1.3em;} | |
.marker-title span{color:#00704A;font-weight:bold;} | |
#findme{display:none;background:#00704A} | |
#kmcount {line-height:2em;color:#00704A} | |
#searchresults {height:0px; overflow:visible; display:none;} | |
input:focus + #searchresults, #searchresults:active {display:block;} | |
.result{background:white; width:160px; display:block; padding:10px; cursor:pointer;line-height:1.4em;} | |
.result:hover {color:#00704A;} | |
.leaflet-container {cursor:default;} | |
.leaflet-marker-icon{cursor:default;} | |
.leaflet-popup-content {padding: 10px;} | |
.leaflet-marker-icon:active ~ * {pointer-events:none;} | |
.leaflet-marker-draggable:hover{cursor:-webkit-grab;} | |
.leaflet-marker-draggable:active{cursor:-webkit-grabbing;} | |
.blocker {color:#00704A; text-align: center} | |
path[stroke-opacity='1'] {stroke-dashoffset: 10000; stroke-dasharray:10000; -webkit-transition:stroke-dashoffset 6s} | |
strong {color:#666;} | |
.distance-icon {border-radius:10px; background:#fff;color:#00704A; text-align:center;display:inline-block; border:2px solid #00704A;} | |
</style> | |
</head> | |
<body> | |
<div id='map'></div> | |
<div class='pin-top fill-white pad1 keyline-bottom quiet space'> | |
<div class='blocker strong large pad0'> | |
Downloading locations... | |
</div> | |
<div id='topbar' style='display:none'> | |
<img src='https://api.mapbox.com/v4/marker/pin-s-water+00704A.png?access_token=pk.eyJ1IjoiZ3JhZmEiLCJhIjoiZjk3Mjk2YWYzZTNlYjM3ODdlNzJlOWJlM2VjZGI0ZDEifQ.OTT9oT7CqAc9vZsnJLT51Q' style='width:30px;margin-right:10px'> | |
<span id='kmcount' class='strong'>0</span> locations within <span id='distance'>a km</span> from here | |
<span class='button short fr icon satellite' id='findme'>Find me</span> | |
<fieldset class="fr with-icon inline"> | |
<span class="icon search" style='top:5px; left:5px'></span> | |
<input type="text" placeholder='Search' class="round short" autocomplete="off" style='width:160px;margin-right:10px'> | |
<div id='searchresults'> | |
</div> | |
</fieldset> | |
</div> | |
</div> | |
<script> | |
L.mapbox.accessToken = 'pk.eyJ1IjoiZ3JhZmEiLCJhIjoiY2lobXN2N3NvMG9ydnRjbHo0N256ZXNtOCJ9.r15Bm_OspE6_qVeqnnJV4w'; | |
var map = L.mapbox.map('map', 'grafa.l94ba424',{ zoomControl: false }) | |
.setView([-43.51805784723727,172.6277446746826], 12); | |
new L.Control.Zoom({ position: 'bottomleft' }).addTo(map); | |
var marker = L.marker(new L.LatLng(-43.51805784723727,172.6277446746826), { | |
icon: L.mapbox.marker.icon({ | |
"marker-color": "#00704A", | |
"title": "You need coffee", | |
"marker-symbol": "pitch", | |
"marker-size": "large" | |
}), | |
draggable: true, | |
zIndexOffset:999 | |
}); | |
var currentPosition; | |
var currentRadius =1; | |
//Geocoder lookup | |
var geocoder = L.mapbox.geocoder('mapbox.places-v1'); | |
//geolocation | |
function getLocation() { | |
if (navigator.geolocation) { | |
navigator.geolocation.getCurrentPosition(showPosition); | |
} | |
} | |
function showPosition(position) { | |
$('#findme').show(); | |
currentPosition=[position.coords.latitude, position.coords.longitude]; | |
} | |
function pointBuffer (pt, radius, units, resolution) { | |
var ring = [] | |
var resMultiple = 360/resolution; | |
for(var i = 0; i < resolution; i++) { | |
var spoke = turf.destination(pt, radius, i*resMultiple, units); | |
ring.push(spoke.geometry.coordinates); | |
} | |
if((ring[0][0] !== ring[ring.length-1][0]) && (ring[0][1] != ring[ring.length-1][1])) { | |
ring.push([ring[0][0], ring[0][1]]); | |
} | |
return turf.polygon([ring]) | |
} | |
$.get('water.geojson', function(data){ | |
$('.blocker').remove(); | |
$('#topbar').show(); | |
var fc = (data); | |
var fc = JSON.parse(data); | |
//find me functionality | |
$('#findme').on('click', function(){ | |
marker.setLatLng(currentPosition); | |
map.setView(currentPosition, 14); | |
updateVenues(); | |
}); | |
//click-move functionality | |
map.on('click',function(e){ | |
marker.setLatLng([e.latlng.lat, e.latlng.lng]); | |
map.setView([e.latlng.lat, e.latlng.lng],14); | |
updateVenues(); | |
}); | |
//input search functionality | |
$('fieldset input').keyup(function(event) { | |
var contents=$('fieldset input').val(); | |
var url='https://api.tiles.mapbox.com/v4/geocode/mapbox.places/'+contents+'.json?access_token='+L.mapbox.accessToken; | |
$.get(url, function(data){ | |
$('.result').remove(); | |
data.features.forEach(function(result){ | |
var place = result['place_name']; | |
var reg = new RegExp(contents,"gi"); | |
place = place.replace(reg, function (match) {return "<strong>" + match + "</strong>"}); | |
$('#searchresults') | |
.append('<div class="result keyline-bottom keyline-left keyline-right small">'+place+'</div>') | |
}); | |
$('.result').each(function(index){ | |
var coords= (data.features[index]['center']); | |
$(this).on('click', function(){ | |
map.setView([coords[1], coords[0]], 13); | |
marker.setLatLng([coords[1], coords[0]]); | |
updateVenues(); | |
}) | |
}) | |
}) | |
if (event.keyCode == 13) { | |
geocoder.query(contents, showMap); | |
$('input').blur(); | |
} | |
}); | |
function showMap(err, data) { | |
map.setView([data.latlng[0], data.latlng[1]], 13); | |
marker.setLatLng([data.latlng[0], data.latlng[1]]); | |
updateVenues(); | |
} | |
//mousewheel functionality (adjust radius) | |
$('.leaflet-marker-draggable').on('mousewheel',function(event){ | |
var wheelDelta= event.originalEvent.wheelDeltaY; | |
if (currentRadius-wheelDelta*0.001>=0.5 && currentRadius-wheelDelta*0.001<=2){ | |
currentRadius=currentRadius-wheelDelta*0.001; | |
updateVenues(); | |
var distancePhrase; | |
switch (parseFloat(currentRadius.toFixed(2))) { | |
case 0.50: | |
distancePhrase = 'a half km' | |
break; | |
case 1.00: | |
distancePhrase = 'a km' | |
break; | |
case 2.00: | |
distancePhrase = 'two kilometers' | |
break; | |
default: | |
distancePhrase = currentRadius.toFixed(2)+' kilometers' | |
break; | |
} | |
$('#distance').html(distancePhrase); | |
} | |
event.stopPropagation(); | |
return false; | |
}); | |
// get position, get radius, draw buffer, find within, calculate distances, find nearest, add to map | |
function updateVenues(){ | |
$('path').remove(); | |
$('.leaflet-marker-pane *').not(':first').remove(); | |
var position=marker.getLatLng(); | |
var point=turf.point(position.lng, position.lat); | |
//draw buffer | |
var bufferLayer = L.mapbox.featureLayer().addTo(map); | |
var buffer = pointBuffer(point, currentRadius, 'kilometers', 120); | |
buffer.properties = { | |
"fill": "#00704A", | |
"fill-opacity":0.05, | |
"stroke": "#00704A", | |
"stroke-width": 2, | |
"stroke-opacity": 0.5 | |
}; | |
bufferLayer.setGeoJSON(buffer); | |
var within = turf.featurecollection(fc.features.filter(function(shop){ | |
if (turf.distance(shop, point, 'kilometers') <= currentRadius) return true; | |
})); | |
$('#kmcount').html(within.features.length); | |
function kmConvert(km){ | |
if (km<=0.5){ | |
return (km*.001).toFixed(0)+' m' | |
} else { | |
return km.toFixed(2) +' km' | |
} | |
} | |
function checkPhone(phone){ | |
if(phone!==null && phone!=='null'){ | |
return '<br>☎ '+phone | |
} else { | |
return ''} | |
} | |
within.features.forEach(function(feature){ | |
var distance = parseFloat(turf.distance(point, feature, 'kilometers')); | |
feature.properties["marker-color"] = "#6E6E6E"; | |
feature.properties["title"] = '<span>'+kmConvert(distance)+'</span><br>' | |
// +feature.properties["street"]+'<br>'+feature.properties["city"]+', '+feature.properties["subcountry"]+' '+feature.properties["country"]+checkPhone(feature.properties["phone"])+'<br> | |
+ '<strong>Click for walking route</strong>'; | |
feature.properties["marker-size"] = "small"; | |
feature.properties["marker-symbol"] = "water"; | |
}) | |
var nearest = turf.nearest(point, fc); | |
var nearestdist = parseFloat(turf.distance(point, nearest, 'kilometers')); | |
nearest.properties["marker-color"] = "#00704A"; | |
nearest.properties["title"] = '<span>'+kmConvert(nearestdist)+' (nearest)</span><br>' + | |
//+nearest.properties["street"]+'<br>'+nearest.properties["city"]+', '+nearest.properties["subcountry"]+' '+nearest.properties["country"]+ checkPhone(nearest.properties["phone"])+' | |
'<br><strong>Click for walking route</strong>'; | |
nearest.properties["marker-size"] = "medium"; | |
nearest.properties["marker-symbol"] = "water"; | |
var nearest_fc = L.mapbox.featureLayer().setGeoJSON(turf.featurecollection([within, nearest])).addTo(map); | |
// hover tooltips and click to zoom/route functionality | |
nearest_fc | |
.on('mouseover', function(e) { | |
e.layer.openPopup(); | |
}) | |
.on('mouseout', function(e) { | |
e.layer.closePopup(); | |
}) | |
.on('click', function(e){ | |
// assemble directions URL based on position of user and selected cafe | |
var startEnd= position.lng+','+position.lat+';'+e.latlng.lng+','+e.latlng.lat; | |
var directionsAPI = 'https://api.tiles.mapbox.com/v4/directions/mapbox.walking/'+startEnd+'.json?access_token='+L.mapbox.accessToken; | |
// query for directions and draw the path | |
$.get(directionsAPI, function(data){ | |
var coords= data.routes[0].geometry.coordinates; | |
coords.unshift([position.lng, position.lat]); | |
coords.push([e.latlng.lng, e.latlng.lat]); | |
var path = turf.linestring(coords, { | |
"stroke": "#00704A", | |
"stroke-width": 4, | |
"opacity":1 | |
}); | |
$('.distance-icon').remove(); | |
map.fitBounds(map.featureLayer.setGeoJSON(path).getBounds()); | |
window.setTimeout(function(){$('path').css('stroke-dashoffset',0)},400); | |
var duration= parseInt((data.routes[0].duration)/60); | |
if (duration<100){ | |
L.marker([coords[parseInt(coords.length*0.5)][1],coords[parseInt(coords.length*0.5)][0]],{ | |
icon: L.divIcon({ | |
className: 'distance-icon', | |
html: '<strong style="color:#00704A">'+duration+'</strong> <span class="micro">min</span>', | |
iconSize: [45, 23] | |
})}) | |
.addTo(map); | |
} | |
}) | |
}); | |
} | |
marker.on('drag', function(){updateVenues()}); | |
updateVenues(); | |
}); | |
getLocation(); | |
marker.addTo(map); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment