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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With