Mapin
Mapin

Reputation: 85

Change icon opacity when hover(symbol layer), in Mapbox GL JS

I see in the documentation that icon-opacity supports feature-state, https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#paint-symbol-icon-opacity

Therefore I use this code for making a change of opacity when user hovers over a icon:

map.addLayer({
    type: 'symbol',
    layout: {
        'icon-image': 'point',
        ...
     },
     paint: {
         'icon-opacity':  
             ['case', ['boolean', ['feature-state','hover'], false], 1, 0.3]
     }
});

The problem is that it takes the original opacity right(0.3) but does not change on hover.

Any idea?

Thanks.

Upvotes: 5

Views: 4350

Answers (1)

jscastro
jscastro

Reputation: 3780

The code you´re posting is right, but it's only half of the solution.

You already implemented the definition of the layer paint behavior for any feature (by default 0.3 as you say), the second part is to change the feature-state hover to true on mouseover.

The state of the features on 'hover' in your symbol layer don´t change automatically, you need to change it to true in a map.on('mousemove', 'youLayerId'... method, and again to false in a map.on('mouseout', 'youLayerId'... .

Check out this fiddle I have created for you on how to change opacity of an icon. enter image description here

The relevant code is below

        mapboxgl.accessToken = 'PUT HERE YOUR TOKEN';
        var map = new mapboxgl.Map({
          container: 'map',
          style: 'mapbox://styles/mapbox/streets-v11'
        });
        let fHover = null;
        map.on('load', function() {
          map.loadImage(
            'https://upload.wikimedia.org/wikipedia/commons/7/7c/201408_cat.png',
            function(error, image) {
              if (error) throw error;
              map.addImage('cat', image);
              map.addSource('point', {
                'type': 'geojson',
                'generateId': true,
                'data': {
                  'type': 'FeatureCollection',
                  'features': [{
                    'type': 'Feature',
                    'geometry': {
                      'type': 'Point',
                      'coordinates': [0, 0]
                    }
                  }]
                }
              });
              map.addLayer({
                'id': 'points',
                'type': 'symbol',
                'source': 'point',
                'layout': {
                  'icon-image': 'cat',
                  'icon-size': 0.25,
                },
                'paint': {
                  'icon-opacity': [
                    'case',
                    ['boolean', ['feature-state', 'hover'], false],
                    1,
                    0.3
                  ]
                }
              });
            }
          );

          map.on('mousemove', 'points', function(e) {
            if (e.features[0]) {
              mouseover(e.features[0]);
            } else {
              mouseout();
            }

          });

          map.on('mouseout', 'points', function(e) {
            mouseout();
          });

          function mouseover(feature) {
            fHover = feature;
            map.getCanvasContainer().style.cursor = 'pointer';

            map.setFeatureState({
              source: 'point',
              id: fHover.id
            }, {
              hover: true
            });
          }

          function mouseout() {
            if (!fHover) return;
            map.getCanvasContainer().style.cursor = 'default';
            map.setFeatureState({
              source: 'point',
              id: fHover.id
            }, {
              hover: false
            });
            fHover = null;

          }
        });

Important, to change a feature state every feature must have an id in the source, so I strongly recommend to set always 'generateId': true in the addSource method.

PS.- If this answer solves your question, please mark it as answer accepted, in that way it will also help other users to know it was the right solution.

Upvotes: 4

Related Questions