Combining tooltips for multiple Leaflet markers of the same location when using GeoJSON FeatureCollections?

Viewed 73

We've got a Leaflet map containing markers and some of them have the same location, and we want to combine tooltips for markers of the same location. I asked about this, providing a simplified reproducible eg, and a comment linked to an answer on a different thread which elegantly solved the issue with JS. Our problem now is that we barely know JS and don't know how to adapt this to our oversimplified eg.

Our previous reproducible eg. built markers individually (eg. L.marker([51.5, -0.4]).bindPopup("single popup").addTo(myMap);), but we did this for question simplicity and our real code uses GeoJSON FeatureCollection. Adapting our previous eg to use this:

<!DOCTYPE html>
    <style>
        html,
        body {
            margin: 0px;
            height: 100%;
        }

        body {
            display: flex;
        }
    </style>
<body>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
        integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
        crossorigin="" />
    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
        integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
        crossorigin=""></script>
    <script src="https://unpkg.com/lodash@4.17.21/lodash.js"></script>

    <div id="mapid" style="flex: 1"></div>
    <script>var myMap = L.map("mapid");
        L.tileLayer('https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', { attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', }).addTo(myMap);
        myMap.setView([51.5, -0.09], 10);

        var geojsonFeatureCollection =
        {
            "type": "FeatureCollection",
            "features": [{
                "type": "Feature",
                "geometry": {
                    "type": "Point",
                    "coordinates": [-0.09,51.5]
                },
                "properties": {
                    "prop0": "text to show in combined pop up",
                    "ignore": "ignore this text"
                }
            },
            {
                "type": "Feature",
                "geometry": {
                    "type": "Point",
                    "coordinates": [-0.09,51.5]
                },
                "properties": {
                    "prop0": "more text to show in combined pop up",
                    "ignore": "ignore this text"
                }
            },
            {
                "type": "Feature",
                "geometry": {
                    "type": "Point",
                    "coordinates": [-0.4,51.5]
                },
                "properties": {
                    "prop0": "single popup",
                    "ignore": "ignore this text"
                }
            }]
        }

        L.geoJSON(geojsonFeatureCollection, {
    pointToLayer: function (feature, coordinates) {
        return L.marker(coordinates);
    }
})
.bindPopup((layer) => layer.feature.properties.prop0)
.addTo(myMap);
    </script>
</body>
</html>

The answer that comment linked to a demo which used JSON data for the points which is close to but not quite the same as FeatureCollection. It used Lodash to group items up by "name", which seems a property of each JSON item: var groupedData = _.groupBy(data, "name");, but we don't know how to do the same with the "features.geometry.coordinates" property of our data.

How can we group GeoJSON FeatureCollection data up like this to combine markers of the same location and then customize tooltips (eg. use the text from "prop0" and other fields)?

1 Answers

You should be able to rework (possibly in runtime) your GeoJSON data with a very similar method as proposed in Bind more popups to the same marker or merge popups content

If I understand correctly, in your case you do not have a property that you can use to identify same locations (was "name" in the linked post), so you can only use the coordinates to determine if Point features should be merged together?

In that case, you could have something in the lines of:

const groupedByCoords = _.groupBy(
  geojsonFeatureCollection.features,
  (feature) => feature.geometry.coordinates
);

const features = [];

     // Rework the Features to merge content
     for (const key in groupedByCoords){
       const items = groupedByCoords[key];
       const mergedContent = items.map((item) => item.properties.prop0).join("<br/>");
       const feature = _.cloneDeep(items[0]);
       feature.properties.prop0 = mergedContent;
       features.push(feature);
     }

// Replace your features
geojsonFeatureCollection.features = features;

Screenshot result Marker with popup and combined text

Live demo: https://plnkr.co/edit/G4Laa9MIvTLkEFlo

Related