Adheesh
Adheesh

Reputation: 83

Display a popup for each cluster marker with custom properties mapbox

I am displaying custom markers with an image icon and displaying the number of markers based on the zooming level. How do I add a popup window to each of these markers?

This is the code I used to plot all the markers.

map.on('load', function () {

    // add a clustered GeoJSON source for a sample set of earthquakes
    map.addSource('earthquakes', {
        "type": "geojson",
        "data": "https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson",
        "cluster": true,
        "clusterRadius": 80
        });


    map.addLayer({
        "id": "cluster",
        "type": "symbol",
        "source": "earthquakes",
        "filter": ["!=", "cluster", true]
        });

    // objects for caching and keeping track of HTML marker objects (for performance)
    var markers = {};
    var markersOnScreen = {};

    function updateMarkers(){
        var newMarkers = {};
        var features = map.querySourceFeatures( 'earthquakes' );

        for ( var i = 0; i < features.length; i++ ) {
            var coords = features[ i ].geometry.coordinates;
            var props = features[ i ].properties;

            if (!props.cluster) continue;
            var id = props.cluster_id;

            var marker = markers[id];

            if (!marker) {
                var el = new Image();
                el.src = 'icon.png';
                el.classList.add( 'mapMarker' );
                el.dataset.type = props.type; // you can use custom data if you have assigned it in the GeoJSON data
                marker = markers[id] = new mapboxgl.Marker({element: el}).setLngLat(coords);

            }

            newMarkers[id] = marker;

            if (!markersOnScreen[id])
                marker.addTo(map);


        }
        // for every marker we've added previously, remove those that are no longer visible
        for (id in markersOnScreen) {
            if (!newMarkers[id])
                markersOnScreen[id].remove();
        }
        markersOnScreen = newMarkers;
    }


    // after the GeoJSON data is loaded, update markers on the screen and do so on every map move/moveend
    map.on('data', function (e) {
        if (e.sourceId !== 'earthquakes' || !e.isSourceLoaded) return;

        map.on('move', updateMarkers);
        map.on('moveend', updateMarkers);
        updateMarkers();
    });

});

I tried this but does not help.

map.on('click', 'states-layer', function (e) {
new mapboxgl.Popup()
.setLngLat(e.lngLat)
.setHTML(e.features[0].properties.name)
.addTo(map);
});

// Change the cursor to a pointer when the mouse is over the states layer.
map.on('mouseenter', 'states-layer', function () {
map.getCanvas().style.cursor = 'pointer';
});

// Change it back to a pointer when it leaves.
map.on('mouseleave', 'states-layer', function () {
map.getCanvas().style.cursor = '';
});

Also tried marker.popup() function. Any help is greatly appreciated.

Thanks, Adheesh

Upvotes: 0

Views: 2334

Answers (1)

Bruno Falbo
Bruno Falbo

Reputation: 21

Try not to create markers. Instead make a layer for single points in the map. You can add an icon to the layer so it looks like a marker. It works like this:

First you should add layer for points unclustered.

Example with an icon:

map.loadImage('https://imageURL', function(error, image) {
    if (error) throw error;
    map.addImage('IMAGE-NAME', image);

    map.addLayer({
        id: "unclustered-point",
        type: "symbol",
        source: "earthquakes",
        filter: ["!", ["has", "point_count"]],
        layout: {
            "icon-image": 'IMAGE-NAME',
            "icon-size":1,
            }
    });

Example without an icon:

map.addLayer({
        id: "unclustered-point",
        type: "circle",
        source: "earthquakes",
        filter: ["!", ["has", "point_count"]],
    });

Then add a click event:

map.on('click', 'unclustered-point', function (e) {
    new mapboxgl.Popup()
    .setLngLat(e.lngLat)
    .setHTML(e.features[0].properties.description)
    .addTo(map);
    });

Remember to put your code inside of map.on("load"...) function

map.on('load', function() 
{
  //put your code here
}

I think for this to work you would have to not use yours markers code.

Upvotes: 1

Related Questions