[guadec-web: 4/9] improved interactivity



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]