v-mapbox icon indicating copy to clipboard operation
v-mapbox copied to clipboard

Clustering markers on the map

Open ConnorOnTheWeb opened this issue 2 years ago • 3 comments

Clustering with v-mapbox

If I'm working with a lot of pins, I'd like to cluster the pins like this (from gmaps):

Screenshot_20220120_190612

Link to Mapbox Cluster page

Is this a feature we have on hand with v-mapbox, or is there a good way to do this?

ConnorOnTheWeb avatar Jan 21 '22 03:01 ConnorOnTheWeb

You can do this via the geojson-layer w.r.t. this example – https://docs.mapbox.com/mapbox-gl-js/example/cluster/

vinayakkulkarni avatar Jan 21 '22 06:01 vinayakkulkarni

Thank you, we're a step closer. I see the MglGeojsonLayer component in v-mapbox.

How do I translate the vanilla js example from the Mapbox docs to the format that works with vue and v-mapbox? Where do I input the array that I have working with the Markers and how to handle popups?

ConnorOnTheWeb avatar Jan 21 '22 07:01 ConnorOnTheWeb

I've got clustering working, from this vanilla js example https://codepen.io/pen/?editors=0010

Looks perfect! Only thing I'm hung up on now is adding the events

This is the vanilla js code for the events:

// inspect a cluster on click
map.on('click', 'clusters', (e) => {
    const features = map.queryRenderedFeatures(e.point, {
        layers: ['clusters']
    });
    const clusterId = features[0].properties.cluster_id;
    map.getSource('earthquakes').getClusterExpansionZoom(
        clusterId,
        (err, zoom) => {
            if (err) return;

            map.easeTo({
                center: features[0].geometry.coordinates,
                zoom: zoom
            });
        }
    );
});

// popup over point on click
map.on('click', 'unclustered-point', (e) => {
    const coordinates = e.features[0].geometry.coordinates.slice();
    const mag = e.features[0].properties.mag;
    const tsunami =
        e.features[0].properties.tsunami === 1 ? 'yes' : 'no';

    while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
        coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
    }

    new mapboxgl.Popup()
        .setLngLat(coordinates)
        .setHTML(
            `magnitude: ${mag}<br>Was there a tsunami?: ${tsunami}`
        )
        .addTo(map);
});

map.on('mouseenter', 'clusters', () => {
    map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'clusters', () => {
    map.getCanvas().style.cursor = '';
});

I don't see how to add these events to the map in the v-mapbox documentation.

This is my MglGeojsonLayer component:

<MglGeojsonLayer
  v-for="(layer, idx) in layers"
  :key="idx"
  :source-id="layer.source"
  :source="geoJsonSource"
  :layer-id="layer.id"
  :layer="layer"
  :clear-source="true"
  :replace="true"
/>

I'm thinking I need to add these:

@click="onClick"
@mouseenter="mouseEnter"
@mouseleave="mouseLeave"

In nuxt methods, how can I effect the same changes to the map? (zoom in on cluster, display popup, etc)

Also how can I insert a component into the popup?

ConnorOnTheWeb avatar Jan 29 '22 07:01 ConnorOnTheWeb

  • [x] Repro done here – https://github.com/vinayakkulkarni/cluster

vinayakkulkarni avatar Mar 09 '23 20:03 vinayakkulkarni