1
votes

I have a gray layer to display multiple polygons on the Mapbox map. I'm attempting to change the color of only one of them when the user clicks on it to display the "selected" the polygon. I don't want interaction, that's why I'm not using the Draw library, just to show the selected polygon.

enter image description here

Is there any way to do it in just one layer?? I tried adding a boolean property called "selected" to each polygon property, but I didn't achieve to update the layer.

// Define polygons with properties
var features = [];
areas.forEach(area => features.push(turf.polygon(area.polygon, { id_area: area.id_area, name: area.name, selected: 'false' })));
features = turf.featureCollection(features);

map.on('load', function () {
    // Add polygons to map
    map.addSource('areas', {
        'type': 'geojson',
        'data': features
    });
    // Layer settings
    map.addLayer({
        'id': 'polygons',
        'type': 'fill',
        'source': 'areas',
        'paint': {
            'fill-color': [
                'match',
                ['get', 'selected'],
                'true', '#64bdbb', // if selected true, paint in blue
                '#888888' // else paint in gray
            ],
            'fill-opacity': 0.4
        },
        'filter': ['==', '$type', 'Polygon']]
    });
}); 
// Click on polygon
map.on('click', 'polygons', function (e) {
    if(e.features.length) {
        var feature = e.features[0];
        if (feature.properties.id_area == id) {
            feature.properties.selected = 'true';
        } else {
            feature.properties.selected = 'false';
        }


        // How can I update the layer here to repaint polygons????


    }
});

Thank you in advance!

1

1 Answers

7
votes

You can use a click event and feature states to change a polygon's color when selected. I put together an example of this in a CodePen here, which is based on this example from Mapbox. Code:

mapboxgl.accessToken = 'pk.eyJ1IjoicGxtYXBib3giLCJhIjoiY2s3MHkzZ3VnMDFlbDNmbzNiajN5dm9lOCJ9.nbbtDF54HIXo0mCiekVxng';
var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v11',
    center: [-100.486052, 37.830348],
    zoom: 2
});
var clickedStateId = null;

map.on('load', function() {
    map.addSource('states', {
        'type': 'geojson',
        'data':
            'https://docs.mapbox.com/mapbox-gl-js/assets/us_states.geojson'
    });

    // The feature-state dependent fill-color expression will render the click effect
    // when a feature's click state is set to true.
    map.addLayer({
        'id': 'state-fills',
        'type': 'fill',
        'source': 'states',
        'layout': {},
        'paint': {
            'fill-color': [
                'case',
                ['boolean', ['feature-state', 'click'], false],
                '#64bdbb',
                '#888888'
            ]
        }
    });

    map.addLayer({
        'id': 'state-borders',
        'type': 'line',
        'source': 'states',
        'layout': {},
        'paint': {
            'line-color': '#627BC1',
            'line-width': 1
        }
    });

    // When the user clicks we'll update the
    // feature state for the feature under the mouse.
    map.on('click', 'state-fills', function(e) {
        if (e.features.length > 0) {
            if (clickedStateId) {
                map.setFeatureState(
                    { source: 'states', id: clickedStateId },
                    { click: false }
                );
            }
            clickedStateId = e.features[0].id;
            map.setFeatureState(
                { source: 'states', id: clickedStateId },
                { click: true }
            );
        }
    });
});

Disclaimer: I work at Mapbox