6

I have a geojson layer of streets that are highlighted when moused-over.

My objective is now to highlight individual streets red with a click event. Only one street should be able to be highlighted at a time, and should remain highlighted until a different street is clicked.

All of my attempts so far have failed. Any idea as to what needs to be added to the following code?

<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>HTML markers from geoJSON url</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.15.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.15.0/mapbox-gl.css' rel='stylesheet'/>
<style>
  body { margin:0; padding:0; }
  #map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map'></div>

<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiaXNrYW5kYXJibHVlIiwiYSI6ImNpbHIxMXA3ejAwNWl2Zmx5aXl2MzRhbG4ifQ.qsQjbbm1A71QzVg8OcR7rQ';


var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/dark-v8',
    center: [37.625224, 55.744537,],
    zoom: 13
});

map.on('style.load', function () {
    map.addSource('streets', {
        "type": "geojson",
        "data": "https://iskandarblue.github.io/mapbox/data/simplify_prototype.geojson"
    });




    map.addLayer({
        "id": "m_streets",
        "type": "line",
        "source": "streets",
        "interactive": true,
        "layout": {},
        "paint": {
            "line-color": "#627BC1",
            "line-opacity": 0.0,
            "line-width": 2.5
        }
    });

    map.addLayer({
        "id": "route-hover",
        "type": "line",
        "source": "streets",
        "layout": {},
        "paint": {
            "line-color": "#f48024",
            "line-opacity": 0.9,
            "line-width": 2.5
        },
        "filter": ["==", "rd_name", ""]
    });

    map.addLayer({
    "id" : "street_toggle",
    "source": "streets",
    "type": "line",
    "layout": {"line-join": "round",
              "line-cap": "round"},
    "paint": {
        "line-color": "#FF0000",
        "line-opacity": 0.9,
        "line-width:": 3.5
      }
     });

    map.on('mousemove', function(e) {
        map.featuresAt(e.point, {
            radius: 5,
            layer: ["m_streets"]
        }, function (err, features) {
            if (!err && features.length) {
                map.setFilter('route-hover', ['==', 'rd_name', features[0].properties.rd_name]);
            } else {
                map.setFilter('route-hover', ['==', 'rd_name', '']);
            }
        });
    });

    map.on('click', function(e) {
        map.featuresAt(e.point, {
            radius: 5,
            layer: ["street_toggle"]
        }, function (err, features) {
            if (!err && features.length) {
                map.setFilter('street_toggle', ['==', 'rd_name', features[0].properties.rd_name]);
            } else {
                map.setFilter('street_toggle', ['==', 'rd_name', '']);
            }
        });
    });


});


   //.addTo(map);


</script>
</body>
</html>
6

You can query the feature using queryRenderedFeature() (you need to upgrade from v0.15 to v0.16) then send the results back into a new layer... This is how I "select" data in most of my apps.

I removed your hover code and added colored streets/selected features for ease of understanding.

I think you could avoid adding geojson and add the resultant vectortilefeature... but geojson is what i know best.

<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>HTML markers from geoJSON url</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.16.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.16.0/mapbox-gl.css' rel='stylesheet'/>
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map'></div>

<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiaXNrYW5kYXJibHVlIiwiYSI6ImNpbHIxMXA3ejAwNWl2Zmx5aXl2MzRhbG4ifQ.qsQjbbm1A71QzVg8OcR7rQ';


var map = new mapboxgl.Map({
     container: 'map',
     style: 'mapbox://styles/mapbox/dark-v8',
     center: [37.625224, 55.744537,],
     zoom: 13
});

map.on('style.load', function () {
    map.addSource('streets', {
    "type": "geojson",
    "data": "https://iskandarblue.github.io/mapbox/data/simplify_prototype.geojson"
    });

map.addLayer({
    "id": "m_streets",
    "type": "line",
    "source": "streets",
    "interactive": true,
    "layout": {},
    "paint": {
        "line-color": "red",
        // "line-opacity": 0.0,
       "line-width": 2.5
    }
});

map.on('click', function(e) {
    var features = map.queryRenderedFeatures(e.point, { layers: ['m_streets'] });
    if (!features.length) {
        return;
    }
    if (typeof map.getLayer('selectedRoad') !== "undefined" ){         
        map.removeLayer('selectedRoad')
        map.removeSource('selectedRoad');   
    }
    var feature = features[0];
    //I think you could add the vector tile feature to the map, but I'm more familiar with JSON
    console.log(feature.toJSON());
    map.addSource('selectedRoad', {
        "type":"geojson",
        "data": feature.toJSON()
    });
    map.addLayer({
        "id": "selectedRoad",
        "type": "line",
        "source": "selectedRoad",
        "layout": {
            "line-join": "round",
            "line-cap": "round"
        },
        "paint": {
            "line-color": "yellow",
            "line-width": 8
        }
    });
});
});

</script>
</body>
</html>

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.