'Mapbox GL JS Set Paint property on specific Feature in Layer

I am using Mapbox Studio as basis for mapping and styling and then using HTML for additional map features.

One of the features is to change Icon opacity when hovering or mouse enter. I've checked other examples and all other refer to feature when you create it directly in HTML. I managed to change opacity but only for whole layer.

Can I use somehow e.features[0] command line to apply changes only to one feature rather than to whole layer?

I used this code which changer opacity for whole Layer 'Icon' (Layer contains 5 icons with text):

    // Change the cursor to a default and change opacity when the it enters a feature in the 'Icons' layer.
map.on('mouseenter', 'Icons', function() {
    map.getCanvas().style.cursor = 'default';
    var feature = e.features[0];
    map.setPaintProperty('Icons', 'icon-opacity', 0.5);
});

// Change it back to a pointer and reset opacity when it leaves.
map.on('mouseleave', 'Icons', function() {
    map.getCanvas().style.cursor = '',
    map.setPaintProperty('Icons', 'icon-opacity', 1);
});

Thank you!!!



Solution 1:[1]

There are a few ways which you could achieve this. One approach is to add each feature as separate layer, so that when you want to change the opacity of an icon added in a layer 'specific-icon-layer', you can pass 'specific-icon-layer' to the Map#on method. This is likely the most straightforward option if you have a relatively minimal number of markers.

Another approach is to add unique IDs to each icon feature, so that you can use a filter expression in conjunction with Map#setPaintProperty and Map#queryRenderedFeatures (or Map#querySourceFeatures). For example, suppose you add an 'id' property to each GeoJSON feature representing an icon in the source for the 'Icons' layer. Then, you could set up an event listener similar to this example, retrieve the 'id' of the returned feature, and use the 'id' (suppose here it is 'example-id') to update the paint property for the 'Icons' layer:

map.setPaintProperty(
  'Icons', 
  'icon-opacity', 
  ['match', ['get', 'id'], 'example-id', 0.5 , 1]
);

Here, we use match and get expressions to say "if the 'id' of a feature is 'example-id', paint its icon with opacity 0.5, otherwise use opacity 1."

Solution 2:[2]

Check the example at https://docs.mapbox.com/mapbox-gl-js/example/hover-styles/

This approach makes use of setFeatureState and feature-state expressions

The problem with using map.setPaintProperty(layer, property, filter, matchValue, styleValue, fallbackStyleValue) every time is that it restyles every feature on the layer instead of only the feature being interacted with. This can cause poor performance when the layer has a high number of features.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Adriana Babakanian
Solution 2 plong0