简体   繁体   中英

How get features from a style's layer in Mapbox GL JS?

I'm a learner of JavaScript and have a problem with Mapbox GL JS: I have a style in Mapbox Studio, where there is one my layer — "locations" . I've added it as a tileset. There are two GeoJSON-points in this layer, but I can't get them in GL JS. I've found that I should use method querySourceFeatures(sourceID, [parameters]) , but I have problems with correct filling its parameters. I wrote:

var allFeatures = map.querySourceFeatures('_id-of-my-tyleset_', {
  'sourceLayer': 'locations'
});

..and it doesn't work.

More interesting, that later in the code I use this layer with method queryRenderedFeatures , and it's okay:

map.on('click', function(e) {
      var features = map.queryRenderedFeatures(e.point, {
        layers: ['locations']
      });

      if (!features.length) {
        return;
      }
      var feature = features[0];
      flyToPoint(feature);
      var popup = new mapboxgl.Popup({
          offset: [0, -15]
        })
        .setLngLat(feature.geometry.coordinates)
        .setHTML('<h3>' + feature.properties.name + '</h3>' + '<p>' +
          feature.properties.description + '</p>')
        .addTo(map);
    });

I have read a lot about adding layers on a map and know that the answer is easy, but I can't realise the solution, so help, please :)

Here is the project on GitHub.

Your problem is that your map, like all maps created in Mapbox Studio by default, uses auto-compositing. You don't actually have a source called morganvolter.cj77n1jkq1ale33jw0g9haxc0-2haga , you have a source called composite with many sub layers.

You can find the list of layers like this:

map.getSource('composite').vectorLayerIds

Which reveals you have a vector layer called akkerman . (" locations " is the name of your style layer, not your source layer). Hence your query should be:

map.querySourceFeatures('composite', {
  'sourceLayer': 'akkerman'
});

Which returns 4 features.

There are lots of questions about Mapbox get features after filter or Mapbox get features before filter . And I could see there are many posts are scattering around but none of them seem to have a FULL DETAILED solution. I spend some time and put both solution together under a function, try this in jsbin. Here it is for someone interested:

function buildRenderedFeatures(map) {
  // get source from a layer, `mapLayerId` == your layer id in Mapbox Studio    
  var compositeSource = map.getLayer(mapLayerId.toString()).source;
  //console.log(map.getSource(compositeSource).vectorLayers);
  var compositeVectorLayerLength = map.getSource(compositeSource).vectorLayers.length - 1;
  //console.log(compositeVectorLayerLength);
  // sourceId === tileset id which is known as vector layer id
  var sourceId = map.getSource(compositeSource).vectorLayers[compositeVectorLayerLength].id;
  //console.log(sourceId);
  
  // get all applied filters if any, this will return an array    
  var appliedFilters = map.getFilter(mapLayerId.toString());
  //console.log(appliedFilters);
   
  // if you want to get all features with/without any filters
  // remember if no filters applied it will show all features
  // so having `filter` does not harm at all 
  //resultFeatures = map.querySourceFeatures(compositeSource, {sourceLayer: sourceId, filter: appliedFilters});
  var resultFeatures = null;

  // this fixes issues: queryRenderedFeatures getting previous features
  // a timeout helps to get the updated features after filter is applied
  // Mapbox documentation doesn't talk about this! 
  setTimeout(function() {
    resultFeatures = map.queryRenderedFeatures({layers: [mapLayerId.toString()]});
    //console.log(resultFeatures);
    }, 500);
  }

Then you call that function like: buildRenderedFeatures(map) passing the map object which you already have when you created the Mapbox map.

You will then have resultFeatures will return an object which can be iterated using for...in . You can test the querySourceFeatures() code which I commented out but left for if anyone needs it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM