如何从Mapbox GL JS中的样式层获取功能?

时间:2017-09-07 16:58:41

标签: javascript mapbox mapbox-gl-js

我是JavaScript的学习者并且遇到Mapbox GL JS的问题:我在Mapbox Studio中有一个样式,其中有one my layer — "locations"。我已将其添加为tileset。这一层有两个GeoJSON点,但我无法在GL JS中获得它们。 我发现我应该使用方法querySourceFeatures(sourceID, [parameters]),但是我在填写参数时遇到了问题。我写道:

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

..它不起作用。

更有趣的是,稍后在代码中我使用方法queryRenderedFeatures使用此图层,并且没关系:

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);
    });

我已经阅读了很多关于在地图上添加图层的知识,并且知道答案很简单,但我无法实现解决方案,所以请帮助:)

Here is GitHub上的项目。

2 个答案:

答案 0 :(得分:3)

您的问题是,您的地图与默认情况下在Mapbox Studio中创建的所有地图一样,都使用自动合成。您实际上没有名为morganvolter.cj77n1jkq1ale33jw0g9haxc0-2haga的来源,您有一个名为composite的来源,其中包含许多子图层。

你可以找到这样的图层列表:

map.getSource('composite').vectorLayerIds

这表明你有一个名为akkerman的矢量图层。 (&#34; locations&#34;是样式图层的名称,而不是来源图层的名称。因此,您的查询应该是:

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

返回4个功能。

答案 1 :(得分:1)

有很多关于 Mapbox get features after filterMapbox get features before filter 的问题。我可以看到有很多帖子散落着,但似乎没有一个有 FULL DETAILED 解决方案。我花了一些时间将两个解决方案放在一个函数下,在 jsbin 中试试这个。 这是给感兴趣的人:

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);
  }

然后调用该函数,例如:buildRenderedFeatures(map) 传递创建 Mapbox 地图时已有的 map 对象。

然后您将让 resultFeatures 返回一个可以使用 for...in 迭代的对象。您可以测试我注释掉的 querySourceFeatures() 代码,但如果有人需要,可以留着。