vinayakkulkarni/v-mapbox

Clustering markers on the map

ConnorOnTheWeb opened this issue · 4 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?

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

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?

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?