0

I'm using Leaflet markercluster in an app. I have an endpoint where a specific marker is selected (eg. ../marker/12); so the maps centers on that marker and displays its popup when the page loads.

But I also want to display the marker not clustered. Until I'm not aware of another solution, I guess I need to build a custom function to compute the zoom level that displays the marker unclustered.

Here's an unfinished attempt I made (with the help of chatGPT), not sure if the logic works or how to make it work properly.

const getUnclusteredZoomLevel = (activeMarker) => {
  const clusterRadiusInPixels = 80; // Default clustering radius in pixels
  const maxZoom = map.getMaxZoom();
  
  const coordinates = activeMarker.getLatLng();

  //Finds the nearest marker given a marker.
  const getNearestMarkerDistance = (marker) => {
    const coordinates = marker.getLatLng();
    const markersLayer = mapLayer.markers;
    if (!markersLayer || !map.hasLayer(markersLayer)){
      throw new Error('Cannot get marker by ID; the markers layer is missing.')
    }
    const allMarkers = [];
    markersLayer.eachLayer((marker) => {
      allMarkers.push(marker);
    });

    const otherMarkers = allMarkers.filter(item => item !== marker);

    const distances = otherMarkers.map(marker => coordinates.distanceTo(marker.getLatLng()))
    const dist = Math.min(...distances);

    const nearest = otherMarkers.find(marker => coordinates.distanceTo(marker.getLatLng()) === dist)
    console.log("NEAREST MARKER", nearest.feature);

    return dist;
  }
  const minDistance = getNearestMarkerDistance(activeMarker);


  //Compute the zoom level where our marker gets unclustered
  let currentZoom = 0;

  while (currentZoom <= maxZoom) {

    //Get the cluster radius in meters
    const metersPerPixelForZoom = //how to compute this ?
    const clusterRadiusInMeters = clusterRadiusInPixels * metersPerPixelForZoom

    if (minDistance > clusterRadiusInPixelsPixelsAtZoom) {
      break;
    }

    currentZoom++;
  }

  return currentZoom;
};
4
  • What do you mean by "not sure if the logic works "? Did you try it?
    – TomazicM
    Commented May 13 at 19:53
  • Of course. It does not work and those are bits of attempts but I'm not sure it goes it the right direction.
    – gordie
    Commented May 13 at 21:56
  • I've just read about the native function zoomToShowLayer(marker) that zooms at the correct level to see a marker unclustered.
    – gordie
    Commented May 13 at 21:57
  • Did you try it? I tried it and it works as expected/required.
    – TomazicM
    Commented May 14 at 8:25

1 Answer 1

0

I found a solution for my initial question (with the help of chatGPT) - but I ended up not using it; because I adapted my logic to take advantage of the native function zoomToShowLayer(layer, callback); which zooms on a specific marker to display it unclustered.

Anyway, if anyone still search that:

const unclusteredZoom = (map,marker) => {

    // Check if the marker is already unclustered
    if (marker.__parent === null) {
        return map.getZoom();
    }

    // Binary search to find the zoom level where the marker appears unclustered
    let left = 0;
    let right = map.getMaxZoom();
    let result = 0;

    while (left <= right) {
        const mid = Math.floor((left + right) / 2);
        const clusterZoom = marker.__parent._zoom;

        if (clusterZoom < mid) {
            result = mid;
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }

    return result;
};

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.