Skip to content

Instantly share code, notes, and snippets.

@olea
Forked from jsanz/README.md
Created June 14, 2018 11:14
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 olea/6bf599a047d4eefa4ecb3a42db5ce936 to your computer and use it in GitHub Desktop.
Save olea/6bf599a047d4eefa4ecb3a42db5ce936 to your computer and use it in GitHub Desktop.
MapboxGL + OSM data

Simple script to get data (nodes and polygons separately) from OSM using Overpass API and render it on a Mapbox GL map.

This is probably a work in progress.

To do:

  • Work on having to do just a single call to the Overpass API and then split the geometries by type.
  • Better styling
  • Popups?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>TEST</title>
<link rel='stylesheet' href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.css' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.js'></script>
<script src="https://tyrasd.github.io/osmtogeojson/osmtogeojson.js"></script>
<style>
html, body, #map {
margin: 0;
height: 100%;
}
</style>
</head>
<body id='map'>
<script>
/* parameters */
var
/* positron is a light basemap style using OpenMapTiles vector tiles */
/* other styles
OpenMapTiles https://openmaptiles.github.io/positron-gl-style/style-cdn.json
CARTO https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json
*/
basemap_style = 'https://openmaptiles.github.io/positron-gl-style/style-cdn.json',
/* initial center and zoom level, you can use bboxfinder.com to find proper values */
center = [-2.46,36.83],
zoom = 13,
osm_ways = [
27152910, // almeria railway
29220363, // almeria university
435775764, // Civitas
37923960, // airport
36406179, // UAL parking
],
osm_nodes = [
4414057566, // la mala
4433529185 // hortensia
// bus stops:
2870058034, // 292
974730957, // 144
],
main_color = '#4a86cf';
/* parameters */
/* Script */
var
overpass_url = 'http://overpass-api.de/api/interpreter'
map = new mapboxgl.Map({
container: 'map',
style: basemap_style,
center: center,
zoom: zoom,
attributionControl: true
}),
label_layout = {
"text-font": ["Open Sans Regular"],
"text-field": "{name}",
"symbol-placement": "point",
"text-size": 20,
"text-offset": [.25,.25],
"text-anchor": "top-left",
"text-allow-overlap": false
},
label_paint = {
"text-color": main_color
},
/* from https://www.npmjs.com/package/geojson-polygon-center */
polygon_center = function (polygon) {
var minx = miny = 1000
, maxx = maxy = -1000
polygon = polygon[0]
for (var i = 0; i < polygon.length; i++) {
var point = polygon[i]
var x = point[0]
var y = point[1]
if (x < minx) minx = x
else if (x > maxx) maxx = x
if (y < miny) miny = y
else if (y > maxy) maxy = y
}
return {
type: 'Point',
coordinates: [
minx + ((maxx - minx) / 2),
miny + ((maxy - miny) / 2)
]
}
},
/* moves tags up to the main properties function */
tags_to_props = function(geojson){
geojson.features.forEach(function(feature){
tags = feature['properties']['tags'];
Object.assign(feature['properties'], tags);
})
return geojson
},
/* transforms OSM ways into geojson and adds that as
points and labels to the map */
load_ways = function(data){
// Convert all data to points
polys_geojson = osmtogeojson(data);
points = polys_geojson.features.map(function(poly){
copy = JSON.parse(JSON.stringify(poly));
copy['geometry'] = polygon_center(copy.geometry.coordinates);
return copy
});
points_geojson_props = tags_to_props({
'type': 'FeatureCollection',
'features': points
});
map.addLayer({
'id': 'guadec_ways',
'type': 'circle',
'source': {
'type': 'geojson',
'data': points_geojson_props
},
'layout': {
},
'paint': {
'circle-radius': {
'base': 3,
'stops': [[12, 5], [22, 180]]
},
'circle-color': main_color
}
});
map.addLayer({
'id': 'guadec_ways_labels',
'type': 'symbol',
"minzoom": 12,
'source': {
'type': 'geojson',
'data': points_geojson_props
},
'layout': label_layout,
'paint': label_paint
});
},
/* transforms OSM nodes into geojson and adds that as
points and labels to the map */
load_pois = function(data){
points_geojson = osmtogeojson(data);
points_geojson_props = tags_to_props(points_geojson);
map.addLayer({
'id': 'guadec_pois',
'type': 'circle',
'source': {
'type': 'geojson',
'data': points_geojson_props
},
'layout': {},
'paint': {
'circle-radius': {
'base': 3,
'stops': [[12, 5], [22, 180]]
},
'circle-color': main_color
}
});
map.addLayer({
'id': 'guadec_poi_labels',
'type': 'symbol',
"minzoom": 12,
'source': {
'type': 'geojson',
'data': points_geojson_props
},
'layout': label_layout,
'paint': label_paint
});
};
map.on('load', function() {
/*Once map is loaded, get data from OSM to add as a new layer */
// Render ways
console.log('fetching osm ways...')
fetch(overpass_url,{
method: "POST",
body: `[out:xml][timeout:300];
(way(id:${osm_ways.join(',')});)->.a;
(.a; .a >;);out qt;`})
.then(response => response.text())
.then(str => (new window.DOMParser()).parseFromString(str, "text/xml"))
.then(function(data){
console.log('loading ways...')
load_ways(data);
console.log('fetching osm nodes...')
fetch(overpass_url,{
method: "POST",
body: `[out:xml]
[timeout:300];
(
node(id:${osm_nodes.join(',')});
)->.a;
(.a; .a >;);
out qt;`})
.then(response => response.text())
.then(str => (new window.DOMParser()).parseFromString(str, "text/xml"))
.then(function(data){
console.log('loading nodes...')
load_pois(data);
})
.catch(error => console.log("Error:", error));
})
.catch(error => console.log("Error:", error));
});
// Agrega controles de navegación (zoom, rotación) al mapa:
map.addControl(new mapboxgl.NavigationControl());
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment