[guadec-web: 4/9] improved interactivity
- From: Ismael Olea <olea src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [guadec-web: 4/9] improved interactivity
- Date: Mon, 18 Jun 2018 21:16:07 +0000 (UTC)
commit 6a7e0d156f587464a0436bf23e80e64f613f3604
Author: Jorge Sanz <xurxosanz gmail com>
Date: Fri Jun 15 23:45:50 2018 +0200
improved interactivity
content/pages/test-map-v2.md | 455 ++++++++++++++++++++++++++-----------------
1 file changed, 281 insertions(+), 174 deletions(-)
---
diff --git a/content/pages/test-map-v2.md b/content/pages/test-map-v2.md
index ff64289..47600bb 100644
--- a/content/pages/test-map-v2.md
+++ b/content/pages/test-map-v2.md
@@ -3,192 +3,299 @@ Date: 20180615
## OSM Map with MapboxGL
-<div id="map" style="width: 100%; height: 600px;"></div>
+<div id="map" style="width: 100%; height: 100vh;"></div>
<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>
#map {
margin: 0;
height: 100vh;
width: 100%;
}
+ .mapboxgl-popup-content a {
+ color: #4a86cf;
+ text-decoration-line: none;
+ }
+ .mapboxgl-popup-content ul {
+ padding-left: 18px;
+ }
+ .osm-source{
+ font-size: 0.7em;
+ }
</style>
-
+
<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.421,36.823],
- zoom = 12,
- osm_ways = [
- 27152910, // almeria railway
- 29220363, // almeria university
- 435775764, // Civitas
- 37923960, // airport
- //{ osm_id: 36406179, name: 'UAL Parking'}, // UAL parking
- ],
- osm_nodes = [
- 4414057566, // la mala
- 4433529185, // hortensia
- 2870058034, // 292
- 974730957, // 144
- ],
- main_color = '#4a86cf',
- icon = '/theme/img/Gnomelogo-footprint.png';
+ /* parameters */
+ var /* List of ways to include in the map */
+ osm_ways = [
+ 27152910, // almeria railway
+ 29220363, // almeria university
+ 435775764, // Civitas
+ 37923960, // airport
+ { osm_id: 36406179, name: 'UAL Parking'}, // UAL parking
+ ],
+ /* List of nodes to include in the map */
+ osm_nodes = [
+ 4414057566, // la mala
+ { osm_id: 4433529185, name: 'Overriden name'}, // hortensia
+ 2870058034, // 292
+ 974730957, // 144
+ ],
+ /* Basemap 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://basemaps.cartocdn.com/gl/voyager-gl-style/style.json',
+ /* initial center and zoom level, you can use bboxfinder.com to find proper values */
+ center = [-2.421,36.823],
+ zoom = 12,
+ /* Main color to use anywhere */
+ main_color = '#4a86cf',
+ /* Icon for the points ont the map */
+ icon = 'https://i.imgur.com/cux5ypg.png', // '/theme/img/Gnomelogo-footprint.png',
+ /* White list of properties to allow to
+ be displayed in the popup, order matters! */
+ popup_properties = [
+ 'description',
+ 'shop','amenity','wheelchair',
+ 'highway', 'network', 'bench', 'shelter', 'ref',
+ 'adr:street',
+ 'website','wikidata','wikipedia'
+ ]
+ ;
</script>
<script>
- /* 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
- }),
- /* 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)
- ]
- }
- },
- /* Generate a valid OSM Overpass API request */
- get_osm_query = function(){
- return `[out:xml][timeout:300];
- (
- way(id:${osm_ways.join(',')});
- node(id:${osm_nodes.join(',')});
- )->.a;
- (.a; .a >;);out qt;`
- }
- /* 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 data into geojson and adds that as
- points and labels to the map */
- load_osm_data = function(data){
- // Convert to GeoJSON
- var geojson_data = osmtogeojson(data);
-
- // Filter ways
- var polys_geojson = geojson_data.features.filter(function(feature){
- return feature.properties.type == "way"
- });
- // Filter points
- var points_geojson = geojson_data.features.filter(function(feature){
- return feature.properties.type == "node"
- });
-
- // Generate centroids for points
- var polys_geojson_points = polys_geojson.map(function(poly){
- copy = JSON.parse(JSON.stringify(poly));
- copy['geometry'] = polygon_center(copy.geometry.coordinates);
- return copy
- });
-
- // Get all properties out
- var points_geojson_props = tags_to_props({
- 'type': 'FeatureCollection',
- 'features': points_geojson.concat(polys_geojson_points)
- });
-
- console.log(points_geojson_props);
-
- map.loadImage(icon, function(error, image) {
- if (error) throw error;
- map.addImage('gnome', image);
- map.addLayer({
- 'id': 'guadec_icon',
- 'type': 'symbol',
- 'source': {
- 'type': 'geojson',
- 'data': points_geojson_props
- },
- 'layout': {
- "symbol-placement": "point",
- "icon-image": "gnome",
- "icon-allow-overlap": true,
- "icon-size": .15
- },
- 'paint': {}
- });
- map.addLayer({
- 'id': 'guadec_label',
- 'type': 'symbol',
- "minzoom": 12,
- 'source': {
- 'type': 'geojson',
- 'data': points_geojson_props
- },
- '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,
- "text-optional": true,
- },
- 'paint': {
- "text-color": main_color,
- "text-halo-color": "white",
- "text-halo-width": 1,
- "text-halo-blur": 1
- }
- });
- });
- };
-
- /* SCRIPT */
- map.on('load', function() {
- /*Once map is loaded, get data from OSM to add as a new layer */
- // Render ways
- console.log('fetching osm data...')
- fetch(overpass_url,{
- method: "POST",
- body: get_osm_query()})
- .then(response => response.text())
- .then(str => (new window.DOMParser()).parseFromString(str, "text/xml"))
- .then(function(data){
- console.log('loading data...')
- load_osm_data(data);
- })
- .catch(error => console.log("Error:", error));
- });
- // Agrega controles de navegaciĆ³n (zoom, rotaciĆ³n) al mapa:
- map.addControl(new mapboxgl.NavigationControl());
-</script>
\ No newline at end of file
+ /* 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
+ }),
+ /* 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)
+ ]
+ }
+ },
+ /* helper to get the list of ids */
+ get_ids = function(el){
+ if (typeof el == "number"){
+ return el
+ } else {
+ return el['osm_id']
+ }
+ },
+ get_props = function(feature){
+ var properties = feature['properties'],
+ /* feature id */
+ feat_id = properties['id'],
+ /* filter checker */
+ filter_node = function(node){
+ return typeof node != "number" && node['osm_id'] == feat_id;
+ },
+ cand = osm_nodes
+ .filter(filter_node)
+ .concat(osm_ways.filter(filter_node));
+
+ if (cand.length == 1){
+ properties = Object.assign(properties,cand[0]);
+ };
+
+ return feature;
+
+ },
+ /* Generate a valid OSM Overpass API request */
+ get_osm_query = function(){
+
+ var ways = osm_ways.map(get_ids);
+ var nodes = osm_nodes.map(get_ids);
+
+ return `[out:xml][timeout:300];
+ (
+ way(id:${ways.join(',')});
+ node(id:${nodes.join(',')});
+ )->.a;
+ (.a; .a >;);out qt;`
+ }
+ /* moves tags up to the main properties function */
+ tags_to_props = function(feature){
+ properties = feature['properties']
+ tags = properties['tags'];
+ Object.assign(properties, tags);
+ delete properties['tags'];
+
+ // Override the name in Engish, if it exists
+ if (properties['name:en'] != undefined){
+ properties['name'] = properties['name:en']
+ };
+
+ return feature
+ },
+ /* transforms OSM data into geojson and adds that as
+ points and labels to the map */
+ load_osm_data = function(data){
+ console.log('loading data...');
+
+
+ var // Convert to GeoJSON
+ geojson_data = osmtogeojson(data),
+ // Filter ways
+ polys_geojson = geojson_data.features.filter(function(feature){
+ return feature.properties.type == "way"
+ }),
+ // Filter points
+ points_geojson = geojson_data.features.filter(function(feature){
+ return feature.properties.type == "node"
+ }),
+ // Generate centroids for points
+ polys_geojson_points = polys_geojson.map(function(poly){
+ copy = JSON.parse(JSON.stringify(poly));
+ copy['geometry'] = polygon_center(copy.geometry.coordinates);
+ return copy
+ }),
+ // Get together both set of points
+ all_features = points_geojson.concat(polys_geojson_points),
+ // Get all properties out from the tags
+ points_geojson_props = all_features.map(tags_to_props),
+ // Override any custom properties
+ final_points = points_geojson_props.map(get_props),
+ // Build final geojson collection
+ geojson = {
+ 'type': 'FeatureCollection',
+ 'features': final_points
+ };
+
+ console.log(geojson);
+
+ map.loadImage(icon, function(error, image) {
+ if (error) throw error;
+ map.addImage('gnome', image);
+ map.addLayer({
+ 'id': 'guadec_icon',
+ 'type': 'symbol',
+ 'source': {
+ 'type': 'geojson',
+ 'data': geojson
+ },
+ 'layout': {
+ "symbol-placement": "point",
+ "icon-image": "gnome",
+ "icon-allow-overlap": true,
+ "icon-size": .15
+ },
+ 'paint': {}
+ });
+ map.addLayer({
+ 'id': 'guadec_label',
+ 'type': 'symbol',
+ "minzoom": 12,
+ 'source': {
+ 'type': 'geojson',
+ 'data': geojson
+ },
+ '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,
+ "text-optional": true,
+ },
+ 'paint': {
+ "text-color": main_color,
+ "text-halo-color": "white",
+ "text-halo-width": 1,
+ "text-halo-blur": 1
+ }
+ });
+ });
+ };
+
+ /* SCRIPT */
+ map.on('load', function() {
+ /*Once map is loaded, get data from OSM to add as a new layer */
+ // Render ways
+ console.log('fetching osm data...')
+ fetch(overpass_url,{
+ method: "POST",
+ body: get_osm_query()})
+ .then(response => response.text())
+ .then(str => (new window.DOMParser()).parseFromString(str, "text/xml"))
+ .then(load_osm_data)
+ .catch(error => console.log("Error:", error));
+ });
+
+ // Add navigation controls
+ map.addControl(new mapboxgl.NavigationControl());
+
+ // Add a popup interactivity
+ map.on('click', function(e) {
+ var features = map.queryRenderedFeatures(e.point, {
+ layers: ['guadec_icon']
+ });
+
+ if (!features.length) {
+ return;
+ }
+
+ var // get the closest feature
+ feature = features[0],
+ // helper to render the properties
+ get_properties_list = function(properties){
+ return popup_properties.filter(function(key){
+ return (Object.keys(properties).findIndex(x => x == key) > -1)
+ })
+ .map(function(key){
+ if (key == 'website'){
+ return `<li><a href="${properties[key]}">${key}</a></li>`
+ } else if (key == 'wikidata'){
+ return `<li><a
href="https://www.wikidata.org/wiki/${properties[key]}">${key}</a></li>`
+ } else if (key == 'wikipedia'){
+ return `<li><a
href="https://en.wikipedia.org/wiki/${properties[key]}">${key}</a></li>`
+ } else {
+ return `<li><strong>${key}</strong>: ${properties[key]}</li>`
+ }
+ }).join('')
+ };
+ // generate a new popup
+ popup = new mapboxgl.Popup({ offset: [0, -15] })
+ .setHTML(`
+ <h3>${feature.properties.name}</h3>
+ <ul>
+ ${get_properties_list(feature.properties)}
+ </ul>
+ <p class="osm-source"><a
href="https://www.openstreetmap.org/${feature.properties.type}/${feature.properties.id}">Source</a></p>
+ `
+ )
+ .setLngLat(feature.geometry.coordinates)
+ .addTo(map);
+ });
+</script>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]