1

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 Answer 1

7

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

Sign up to request clarification or add additional context in comments.

1 Comment

really useful! For those coming across this, note that you can set arbitrary property as id using "promoteId" option in source definition: docs.mapbox.com/mapbox-gl-js/style-spec/sources/… (i wasn't aware of this and lost an hour scracthing my head :D ). Thanks Patrick!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.