Home > Mobile >  Cannot get features from building source layer in Mapbox GL
Cannot get features from building source layer in Mapbox GL

Time:03-15

What I am trying to achieve here is to paint the building when someone searches an address. This can be achieved with map on click event. But it is not workable with geocoder result event. To get the features from building layer I have to pass {x, y} point to the layer which can be achieved with click event. But when I am using geocoder "result" event, it is giving {latitude, longitude} coordinates not {x, y} point. I also tried to convert these coordinates with map.project() but not correctly point. Is there workaround to achieve this? Checkout my code:


 const bounds = [
        [-97.846976993, 30.167105159], // Southwest coordinates
        [-97.751211018, 30.242129961], // Northeast coordinates
      ];

      const map = new mapboxgl.Map({
        container: "map",
        style: "mapbox://styles/smallcrowd/cl07a4926001b15pnu5we767g",
        center: [-79.4512, 43.6568],
        zoom: 13,
        // maxBounds: bounds,
      });

      // Add the control to the map.
      const geocoder = new MapboxGeocoder({
        accessToken: mapboxgl.accessToken,
        mapboxgl: mapboxgl,
      });

      map.on("load", function () {
        var layers = map.getStyle().layers;

        var labelLayerId;
        for (var i = 0; i < layers.length; i  ) {
          if (layers[i].type === "symbol" && layers[i].layout["text-field"]) {
            labelLayerId = layers[i].id;
            break;
          }
        }

        map.addLayer(
          {
            id: "3d-buildings",
            source: "composite",
            "source-layer": "building",
            type: "fill",
            minzoom: 10,
            paint: {
              "fill-color": "#aaa",
            },
          },
          labelLayerId
        );

        map.addSource("currentBuildings", {
          type: "geojson",
          data: {
            type: "FeatureCollection",
            features: [],
          },
        });
        map.addLayer(
          {
            id: "highlight",
            source: "currentBuildings",
            type: "fill",
            minzoom: 15,
            paint: {
              "fill-color": "#f00",
            },
          },
          labelLayerId
        );

        // Working perfectly on click, it is painting the address but I do not want the address to be clicked rather it should be painted on searched.
        map.on("click", "3d-buildings", (e) => {
          map.getSource("currentBuildings").setData({
            type: "FeatureCollection",
            features: e.features,
          });
        });

        //not working because the 3d-building layer wants input as x,y point which I tried to convert result's coordinates into point but map.project is giving wrong points as compared to mouse clicked points
        geocoder.on("result", (e) => {
          var coordinates = e.result.geometry.coordinates;
          const point = map.project(coordinates);

          const selectedFeatures = map.queryRenderedFeatures(point, {
            layers: ["3d-buildings"],
          });
          console.log(point);
          map.getSource("currentBuildings").setData({
            type: "FeatureCollection",
            features: selectedFeatures.features,
          });
        });
       });


Any help will be appreciated !

CodePudding user response:

So if I understand correctly:

  1. User searches for an address
  2. Map zooms to center around the chosen address
  3. Now you want to know what is the screen X/Y coordinate of the chosen address

It's easy: it's exactly in the center of the viewport. So you can do just something like:

const x = map.getContainer().getClientRects()[0].width / 2;
const y = map.getContainer().getClientRects()[0].height / 2;

You will likely have to wait until the map actually finishes moving and the source features have loaded, after step 1. I would use map.once('idle', ...)

  • Related