Juiblex
Juiblex

Reputation: 35

How to place a clickable marker on top of a clickable polygon in Mapbox GL JS

I made a map with mapbox-gl-js and added parking lot layers that, when clicked, open a popup with directions. Then I placed some clickable markers (for bus stops, accessible parking, etc) on top of the parking lot layer. When I click a marker on the parking lot, the parking lot popup and the marker popup both pop up. How can I prevent the polygon layer from firing the popup if there is a marker popup? I don't want both popups showing.

Here is the relevant code:

// Add a layer showing the parking lots
map.addLayer({
    "id": "parking-layer",
    "type": "fill",
    "source": "parking-buttons",
    "layout": {},
    "paint": {
        "fill-color": "hsla(0, 0%, 0%, 0)",
        "fill-outline-color": "hsla(0, 0%, 0%, 0)"
    }
});

// Add a layer showing the bus stop
map.addLayer({
    "id": "bus",
    "type": "symbol",
    "source": "bus",
    "layout": {
        "icon-image": "{icon}-11",
        "icon-allow-overlap": true
    },
    "paint": {
        "icon-opacity": {"stops": [[15.49, 0], [15.5, 1]]}
    }
});

// When a click event occurs for a polygon, open a popup with details
map.on('click', function (e) {
    var features = map.queryRenderedFeatures(e.point, { layers: ['parking-layer', 'buildings-layer'] });

    if (!features.length) {
        return;
    }

    var feature = features[0];

    // Populate the popup and set its coordinates
    var popup = new mapboxgl.Popup()
        .setLngLat(map.unproject(e.point))
        .setHTML(feature.properties.description)
        .addTo(map);
});

// When a click event occurs for a node, open a popup with details
map.on('click', function (e) {
    var features = map.queryRenderedFeatures(e.point, { layers: ['bus', 'ephone'] });

    if (!features.length) {
        return;
    }

    var feature = features[0];

    // Populate the popup and set its coordinates
    var popup = new mapboxgl.Popup()
        .setLngLat(feature.geometry.coordinates)
        .setHTML(feature.properties.description)
        .addTo(map);
});

Upvotes: 2

Views: 2179

Answers (1)

forrert
forrert

Reputation: 4219

You're registering two separate handlers on the click event, which both end up displaying a pop up if there's overlapping features.

I would try handling different results in one click handler rather than 2:

// When a click event occurs for a polygon, open a popup with details
map.on('click', function (e) {
    var pointFeatures = map.queryRenderedFeatures(e.point, { layers: ['bus', 'ephone'] });

    if (pointFeatures.length > 0) {
        var feature = pointFeatures[0];
        // Populate the popup and set its coordinates
        var popup = new mapboxgl.Popup()
            .setLngLat(feature.geometry.coordinates)
            .setHTML(feature.properties.description)
            .addTo(map);
        return; // don't display any more pop ups
    }

    var polygonFeatures = map.queryRenderedFeatures(e.point, { layers: ['parking-layer', 'buildings-layer'] });

    if (!polygonFeatures.length) {
        return;
    }

    var feature = polygonFeatures [0];

    // Populate the popup and set its coordinates
    var popup = new mapboxgl.Popup()
        .setLngLat(map.unproject(e.point))
        .setHTML(feature.properties.description)
        .addTo(map);
});

Upvotes: 0

Related Questions