mapboxmapbox-gl-jsmapbox-glmapbox-expressions

Mapbox GL JS Change the fill-color's property value based on an expression


I have a chloropleth map with a geojson data source backing it. The data set contains data for each country for two different years, with the fill color based on one of the properties in the JSON. Here is my addLayer code currently, which works fine.

map.addLayer({
                id: 'emissions',
                type: 'fill',
                source: {
                    type: 'geojson',
                    data: './data.json'
                },
                paint: {
                    'fill-color': {
                        property: 'total_2014',
                        type: 'exponential',
                        base: 0.99999,
                        stops: [
                            [3, "hsl(114, 66%, 53%)"],
                            [2806634, "hsl(0, 64%, 51%)"]
                        ]
                    },
                    'fill-opacity': 1
                }
            });

I would like to be able to programatically switch the json property on which the fill color is based, and an expression seems the obvious way to do so, however the following code fails with the error layers.emissions.paint.fill-color.property: string expected, array found.

...
paint: {
                    'fill-color': {
                        property: ['get', propName], // propName var is e.g. 'total_2014'
                        type: 'exponential',
                        base: 0.99999,
                        stops: [
                            [3, "hsl(114, 66%, 53%)"],
                            [2806634, "hsl(0, 64%, 51%)"]
                        ]
                    },
                    'fill-opacity': 1
                }
...

Is there a way to achieve what I'm aiming for? I'm very new to using Mapbox GL JS, so apologies if this is a basic question.


Solution

  • Just in case anyone else happens across this requirement, I found a workaround by updating the map's style property directly. This isn't an exact answer since the approach doesn't use expressions, but the performance of mapbox diffing source and applying the changes is very fast and meets my requirements.

    function loadDataForYear(year) {
        const style = map.getStyle();
        style.layers.find(({ id }) => id === "emissions").paint['fill-color']['property'] = 'total_' + year;
        map.setStyle(style);
    }