mapbox-gl-js version:
1.2.0
browser:
Chrome
Create a simple map
this.map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
zoom: 19, // starting zoom
center: [13.380702060621635, 52.5220511942754]
});
Let's add an layer to the map.
this.map.on('load', async () => {
const controls = new mapboxgl.NavigationControl();
this.map.addControl(controls, 'top-right');
this.map.addSource('foo', {
type: 'geojson',
data: coords
});
this.map.addLayer({
id: 'points',
type: 'circle',
source: 'foo',
paint: {
'circle-radius': 5,
'circle-color': 'hotpink',
},
});
});
Now lets add click() functionality to the map. First, detect a click on the layer with the name points
this.map.on('click', 'points', event => {
console.log('Layer click')
});
Now, detect a click on the map, not on the points layer
this.map.on('click', () => {
console.log('Basemap click')
});
I expect the this.map.on('click', () => {... to be fired only when I do not click on the layer points, hence somewhere next to a point displyed in hotpink on the map.
I expect the this.map.on('click', 'points', event => {... to be fired only when I do click on a point of the layer points.
this.map.on('click', 'points', event => {... works as expected.
this.map.on('click', () => {... fires every time I click on the map, even if I click on the points layer. That is unexpected.
I expect the this.map.on('click', () => {... to be fired only when I do not click on the layer points
events apply to all layers by default, so omitting the layer parameter means the map will listen to clicks on all layers.
However, the demo DOES illustrate a bug where listeners for map-wide clicks will trigger layer-specific listeners
events apply to all layers by default, so omitting the layer parameter means the map will listen to clicks on all layers.
I agree, this is working as intended.
However, the demo DOES illustrate a bug where listeners for map-wide clicks will trigger layer-specific listeners
I couldn't replicate that, when I click on the point it correctly triggers both listeners, and when I click outside the point it correctly only triggers the map wide listener.
馃憤 can no longer reproduce-- might've been a mistake on my end. closing
@andrewharvey @peterqliu
Why does clicking on the point layer trigger a click on the basemap und subsequent functions that may be called, when the basemap is clicked? I dont think that this is expected behaviour. I would think that only the point layer click event gets fired when I click on the point layer. What if I have functions that I only want to call, when I do not click on a layer, but on the basemap (i.e. setting a marker where I clicked?). I would add this functionality in the click event of the basemap
this.map.on('click', event => {
addMarker(event)
});
But with the behaviour demonstrated, the addMarker() function is also called, when I click on the point layer.
That is a possible solution, but it adds complexity when there are a lot of layers
let clickCoords = {};
this.map.on('click', 'points', event => {
clickCoords = event.point;
console.log('Layer click')
});
Now, detect a click on the map, not on the points layer
this.map.on('click', () => {
// check if coords are different, if they are different, execute whatever you need
if (clickCoords.x !== event.point.x && clickCoords.y !== event.point.y) {
console.log('Basemap click');
clickCoords = {};
}
});
Mapbox GL JS doesn't have a concept of a basemap. A map is a style made up of a number of layers. A listener without any layer will trigger when you click on any layer, exactly so you can then do different actions based on different layers which are clicked on.
A listener with a layer is just a shorthand way of doing a listener with no layer + queryRenderedFeatures.
If you want to know when there is a click outside the layer, then you can do a click listener without a layer and then queryRenderedFeatures to check if the click was on your layer or not.