T. Altena
T. Altena

Reputation: 811

Mapbox GL v.0.54: Change icon-image based on click

I'm trying to implement a single-layer in mapbox-GL that shows icons which change when clicked. So far I've attempted the following:

Use a property (after pre-loading the images as active and inactive):

'icon-image': ["case",["boolean", ["feature-state", "clicked"], false],
                                "inactive",
                                "active"
                            ],

And various versions of map.updateImage() to dynamically change the image that is displayed for each point:

map.updateImage(`point1`, map.loadImage('/img/pin_active.png'))
map.updateImage(`point1`, 'active')) //with the image being loaded beforehand as 'active'
map.updateImage(`point1`, map.loadImage('/img/pin_active.png', function(error, image) {
                        if (error) throw error;
                        map.addImage(point1, image);
                    }))

The only solution that does work is using SDF (mapbox gl change icon color) - but this does not work for my icons, which are multi-color (and they get pretty ugly since the SDF format seems to scale badly).

Any ideas on how to approach this?

Upvotes: 1

Views: 2526

Answers (1)

T. Altena
T. Altena

Reputation: 811

Ok, so after a bit of extra fiddling around I found a working solution. Just leaving this here for whoever finds it later.

If we load the images beforehand as strings active and inactive:

            map.loadImage('/img/pin_blue.png', function(error, image) {
                if (error) throw error;
                map.addImage('inactive', image);
            })
            map.loadImage('/img/pin_red.png', function(error, image) {
                if (error) throw error;
                map.addImage('active', image);
            })

we can do the following:

            let data = {} // object that stores the geojson data
            let points = map.queryRenderedFeatures(e.point, {
                layers: ['projects-point']
            })
            if (points.length) {
                data.map(function(item, index) {
                if (item.id === points[0].id) {
                    data[index].properties.image = 'active'
                }
                else
                    data[index].properties.image = 'inactive'
            })
            map.getSource('projects').setData(this.dataObj.data)
            }

Upvotes: 2

Related Questions