Skip to content

Instantly share code, notes, and snippets.

@wboykinm
Last active November 22, 2015 05:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wboykinm/737f1f781fe26e918b7d to your computer and use it in GitHub Desktop.
Save wboykinm/737f1f781fe26e918b7d to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Midpoint BarFinder</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.5/flatly/bootstrap.min.css" rel="stylesheet" integrity="sha256-sHwgyDk4CGNYom267UJX364ewnY4Bh55d53pxP5WDug= sha512-mkkeSf+MM3dyMWg3k9hcAttl7IVHe2BA1o/5xKLl4kBaP0bih7Mzz/DBy4y6cNZCHtE2tPgYBYH/KtEjOQYKxA==" crossorigin="anonymous">
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.11.4/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
#header {
position: absolute;
top: 0;
left: 0;
right: 0;
background: #6E4D74;
z-index: 999;
overflow: auto;
padding: 5px;
opacity: 0.95;
color: #fff;
}
</style>
</head>
<body>
<div id='map'></div>
<div id='header'>
<div class='container'>
<h4>Bars within 5mi of a halfway point between two origins</h4>
</div>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fetch/0.10.1/fetch.min.js'></script>
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.11.4/mapbox-gl.js'></script>
<script src='//api.tiles.mapbox.com/mapbox.js/plugins/turf/v2.0.0/turf.min.js'></script>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiZmFyYWRheTIiLCJhIjoiTUVHbDl5OCJ9.buFaqIdaIM3iXr1BOYKpsQ';
// set up the map
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/faraday2/cih81t9p40010k6lyiniupn8s'
});
// define the start/end points
var site1 = [-73.53873,41.05343],
site2 = [-73.41335,41.48143];
//define directions parameters:
var pathLine = { type: 'Feature', properties: {} };
var waypoints = site1[0] + ',' + site1[1] + ';' + site2[0] + ',' + site2[1];
var url = 'https://api.mapbox.com/v4/directions/mapbox.driving/' + waypoints + '.json?access_token=' + mapboxgl.accessToken;
// start the chain train . . .
map.on('style.load', function () {
// hit the directions api and select the route geometry
fetch(url).then(function(response) {
return response.json();
}).then(function(j) {
pathLine.geometry = j.routes[0].geometry;
return pathLine;
})
.then(function(pathLine){
// add the route to the map
map.addSource("route", {
"type": "geojson",
"data": pathLine
});
map.addLayer({
"id": "route",
"type": "line",
"interactive": true,
"source": "route",
"layout": {
"line-join": "round",
"line-cap": "round"
},
"paint": {
"line-color": "#986579",
"line-width": 6,
"line-dasharray": [1,2],
"line-opacity": 0.8
}
});
return pathLine
})
.then(function(pathLine){
// figure out the length of the route
// (probably available in the response above,
// but what the hell)
return turf.lineDistance(pathLine,'miles');
})
.then(function(travelLength){
// find the location of the halfway point on the route
return turf.along(pathLine,(travelLength/2),'miles');
})
.then(function(midPoint){
// add the midpoint to the map
map.addSource("midPoint", {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": [midPoint]
}
});
// add source as a layer and apply some styles
map.addLayer({
"id": "midPoint",
"interactive": true,
"type": "symbol",
"source": "midPoint",
"layout": {
"icon-image": "government_icon",
"text-field": "Midpoint",
"text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"],
"text-offset": [0, 0.6],
"text-anchor": "top"
},
"paint": {
"text-size": 12
}
});
return midPoint;
})
.then(function(midPoint){
// construct a call to the foursquare api for
// venues within 15km of the midpoint
var cId = 'RU314UA4LCIVRLMV5O2GZDK5W253WBGBBW3WMFACFMYGH0QH';
var cSecret = 'CL3JBZ1Q150J0X1L30LISC0VM21T2DP4N2IICRLVSSJMKMJU';
var foursquare_url = 'https://api.foursquare.com/v2/venues/explore' +
'?client_id=' + cId +
'&client_secret=' + cSecret +
'&v=20151115' +
//'&intent=browse' +
'&radius=8000' +
'&ll=' + midPoint.geometry.coordinates[1] + ',' + midPoint.geometry.coordinates[0] +
'&section=drinks' +
'&callback=';
return foursquare_url;
})
.then(function(foursquare_url){
// make the call to the foursquare api, add the results to the map
function status(response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}
function json(response) {
return response.json()
}
fetch(foursquare_url)
.then(status)
.then(json)
.then(function(data) {
// add the results to the map
var barSites = data.response.groups[0].items;
var barGeojson = [];
for (var i = 0; i < barSites.length; i++) {
var barFeature = {
type: 'Feature',
properties: {
name: barSites[i].venue.name,
address: barSites[i].venue.location.address + ', ' + barSites[i].venue.location.city + ' ' + barSites[i].venue.location.state + ' ' + barSites[i].venue.location.postalCode,
url: barSites[i].venue.url
},
geometry: {
type: 'Point',
coordinates: [
barSites[i].venue.location.lng,
barSites[i].venue.location.lat
]
}
}
barGeojson.push(barFeature);
}
// add the midpoint to the map
map.addSource("bars", {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": barGeojson
}
});
// add source as a layer and apply some styles
map.addLayer({
"id": "bars",
"interactive": true,
"type": "symbol",
"source": "bars",
"layout": {
"icon-image": "wine-glass"
},
"paint": {}
});
// set up the interaction functions
map.on('click', function (e) {
map.featuresAt(e.point, {layer: 'bars', radius: 15, includeGeometry: true}, function (err, features) {
if (err) throw err;
if (features.length) {
var tooltip = new mapboxgl.Popup()
.setLngLat(e.lngLat)
.setHTML('<h1><a href="' + features[0].properties.url + '" target="_blank">' + features[0].properties.name + '</a></h1><p>' + features[0].properties.address + '</p>')
.addTo(map);
}
});
});
map.on('mousemove', function (e) {
map.featuresAt(e.point, {layer: 'bars', radius: 15}, function (err, features) {
if (err) throw err;
map.getCanvas().style.cursor = features.length ? "pointer" : "";
});
});
// pan to cover the target locations
var mapExtent = turf.bboxPolygon(turf.extent(turf.featurecollection(barGeojson)));
var mapBounds = [];
mapBounds.push(mapExtent.geometry.coordinates[0][0], mapExtent.geometry.coordinates[0][2]);
map.fitBounds(mapBounds, { speed: 0.8, padding: 70 });
}).catch(function(error) {
console.log('Request failed', error);
});
})
.then(function(){
// do a ridiculous amount of work just to set a sane map view
// update: I now see the "padding" option. jkjk
var mapContext1 = turf.buffer(turf.point(site1),5,'miles'),
mapContext2 = turf.buffer(turf.point(site2),5,'miles');
var union = turf.union(mapContext1.features[0], mapContext2.features[0]);
var mapExtent = turf.bboxPolygon(turf.extent(union));
var mapBounds = [];
mapBounds.push(mapExtent.geometry.coordinates[0][0], mapExtent.geometry.coordinates[0][2]);
map.fitBounds(mapBounds);
});
});
// tah dah!
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment