queryRenderedFeatures is not working on latest Mapbox Standard Map style
mapbox-gl-js version: ^3.8.0
browser: Any browser
Steps to Trigger Behavior
Create a new map instance using the Mapbox Standard style Add click handler that uses queryRenderedFeatures() Click on various map features (buildings, roads, POIs) Check console output or handler results
Link to Demonstration
React Example
import type { MapRef } from 'react-map-gl';
import MAP, { FullscreenControl, GeolocateControl, NavigationControl, Popup, ScaleControl } from 'react-map-gl';
const MapboxMap: React.FC = () => {
const handleMapClick = (event) => {
const map = mapRef.current.getMap();
const features = map.queryRenderedFeatures(event.point);
console.log('Features:', features); // Returns empty array when clicking on map features
};
return (
<Map
mapStyle="mapbox://styles/mapbox/standard"
onClick={handleMapClick}
// ... other props
>
{/* map contents */}
</Map>
);
Expected Behavior
Clicking on map features (buildings, roads, POIs) should return an array of features with their properties Should work similarly to how it works with 'streets-v12' style
Actual Behavior
queryRenderedFeatures() returns an empty array when clicking on map features No features are detected even when clicking on visible map elements
the latest release notes show these changes which are looking promising:
- Add experimental support for style-defined featuresets, an upcoming way to query features in Mapbox Standard and other fragment-based styles.
- Add experimental Map addInteraction/removeInteraction methods that make it easier to manage map interactions like clicking and hovering over features.
Looking through the source, there is some documentation for this method addInteraction, where we can get data for clicked POIs. 🎉🥳
/**
* Add an interaction — a named gesture handler of a given type.
* *This API is experimental and subject to change in future versions*.
*
* @experimental
* @param {string} id The ID of the interaction.
* @param {Object} interaction The interaction object with the following properties.
* @param {string} interaction.type The type of gesture to handle (e.g. 'click').
* @param {Object} [interaction.filter] Filter expression to narrow down the interaction to a subset of features under the pointer.
* @param {TargetDescriptor} [interaction.featureset] The featureset descriptor to narrow down features to.
* Either `{layerId: string}` to reference features in the root style layer, or `{featuresetId: string, importId?: string}` to reference features in an imported style.
* @param {Function} interaction.handler A handler function that will be invoked on the gesture and receive a `{feature, interaction}` object as a parameter.
* @returns {Map} Returns itself to allow for method chaining.
*
* @example
* map.addInteraction('poi-click', {
* type: 'click',
* handler(e) {
* console.log(e.feature);
* }
* });
*/
addInteraction(id: string, interaction: Interaction) {
this._interactions.add(id, interaction);
return this;
}
Unfortunately I gave it a quick attempt and it was not working, the feature value is just null every time. It would be worth looking through this code to see if I have missed anything:
https://github.com/mapbox/mapbox-gl-js/blob/596da6b8e6bf4ff2530e82fce7edefb4aea33a17/debug/featuresets.html#L4
The reason why it's not working at the moment is because the Standard style doesn't expose interactable elements yet — they need to be defined at the style level to be available for querying. It will become available when the next version of the Standard style is released (hopefully soon).
@mourner Any progress on this release? Is there a beta version we can opt into? I'm in the middle of a code refactor and it would be great if it included this functionality. =] (love what you guys do!)
it seems this functionality has been replaced with the new interactions API https://docs.mapbox.com/mapbox-gl-js/guides/user-interactions/interactions/
The new interactions API works just fine for clicking, hovering, and so on, but I couldn't find a way to programmatically interact with a building, like highlight a specific building when opening a page and etc.
What I'm currently doing (not optimal, and I would really like it if someone has a better approach) is to fake a click on the building based on its coords, and then the interaction would fire and the building would be colored.
This is faulty because when triggering a click at a given coordinate, the angle of the map can cause the click to be on the wrong building. Currently, I'm setting the pitch to 0, coloring the building, and then returning the pitch to its original value.
But this is not elegant and it is error-prone.