0
votes

I don't think there's a solution for this but maybe i'm wrong or it'll be possible in future.

I'm trying to highlight a building in mapbox (3d or 2d) given the exact address or GPS coordinates.

Is it even possible to uniquely identify buildings in mapbox?

I couldn't find anything in their documentation and hacking it in seems difficult since everything is painted on a single canvas. html snippet

1

1 Answers

2
votes

Yes, that's feasible, even a part of a building. Anything represented in Mapbox as a building, is based in 1 or more features. For that you need to query the features and then decide what is the attribute you will use to filter only some features to differentiate the behavior.

Check this out, it's a fiddle on how to change color and pointer on mouse over, where I have added a filter for only one feature id among all of the buildings in NYC, that will become red changing its state ('hover ; true') and the mouse pointer is changed to map.getCanvasContainer().style.cursor = 'pointer'.

enter image description here

This is the relevant code:

    let mapConfig = {
      NYC: {
        origin: [-74.044514, 40.689259, 39],
        center: [-74.0137, 40.70346, 0],
        zoom: 16.2,
        pitch: 60,
        bearing: 35
      }
    }

    mapboxgl.accessToken = 'PUT HERE YOUR TOKEN';
    let point = mapConfig.NYC;
    var map = new mapboxgl.Map({
      style: 'mapbox://styles/mapbox/streets-v11',
      center: point.center,
      zoom: point.zoom,
      pitch: point.pitch,
      bearing: point.bearing,
      container: 'map',
      antialias: true,
      hash: true
    });

    map.on('style.load', function() {

      if (map.getSource('composite')) {
        map.addLayer({
          'id': '3d-buildings',
          'source': 'composite',
          'source-layer': 'building',
          'type': 'fill-extrusion',
          'minzoom': 14,
          'paint': {
            'fill-extrusion-color': [
              'case',
              ['boolean', ['feature-state', 'hover'], false],
              '#ff0000',
              '#ddd'
            ],
            'fill-extrusion-height': ["number", ["get", "height"], 5],
            'fill-extrusion-base': ["number", ["get", "min_height"], 0],
            'fill-extrusion-opacity': 1
          }
        }, 'road-label');
      }

      let fHover;

      map.on('click', function(e) {
        var features = map.queryRenderedFeatures(e.point, {
          layers: ['3d-buildings']
        });
        console.log(features[0].id);
      })

      map.on('mousemove', function(e) {
        var features = map.queryRenderedFeatures(e.point, {
          layers: ['3d-buildings']
        });
        //we will change pointer and color for 42455719
        if (features[0] && features[0].id == 42455719) {
          mouseover(features[0]);
        } else {
          mouseout();
        }

      });

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

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

      }

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

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

    });