K. Weber
K. Weber

Reputation: 2773

Leaflet.js: zoom map to visible markers

I have a leaflet.js map with a collection of markers, which can be shown/hidden in a legend div done with plugin Leaflet.StyledLayerControl (I think this is not too relevant but just in case).

I can capture the event when layers are shown or hidden and in that event I would like to zoom to fit all visible markers.

There are a few questions in SO with a very similar title but most of them pretend to fit zoom to a known collection of markers, which is not my case (some other questions with very similar subject refer to Google maps, not leaflet).

So, the question would be:

A) Can I set zoom to fit all visible markers? B) or, how can I get an array of all visible markers to apply the other solutions seen?

This is how I create markers on map:

const icon_general = L.divIcon({html: '<i class="fas fa-map-marker fa-2x"></i>', iconSize: [20, 20], className: 'node_icon'});

var node_10031 = L.marker([40.7174605,-3.9199218],{ icon: icon_general}).addTo(layer1);
node_10031.bindPopup('<h2>Title</h2>');
var node_10032 = L.marker([40.7184576,-3.9202692],{ icon: icon_general}).addTo(layer1);
node_10032.bindPopup('<h2>Title</h2>');
var node_10032 = L.marker([40.7361371,-3.9453966],{ icon: icon_general}).addTo(layer2);
node_10032.bindPopup('<h2>Title</h2>');

Layers are then hidden or shown and I can capture that event, that is where I want to modifiy zoom or loop through visible markers.

EDIT (final solution based on Seth Lutske response):

This is my final solution, maybe it's less eficient as on each click it loops through all visible markers in map, but after some attempts this was the succesful one (I wasn't able to manage properly the individual events for add/remove layer):

function setZoom2Visible()
{
    var visibleLayerGroup = new L.FeatureGroup();

    mymap.eachLayer(function(layer){
        if (layer instanceof L.Marker)
            visibleLayerGroup.addLayer(layer);
    });

    const bounds = visibleLayerGroup.getBounds();
    mymap.fitBounds(bounds);
}

$('.menu-item-checkbox input[type=checkbox]').click(function(){
    setZoom2Visible();
});

Upvotes: 0

Views: 1146

Answers (1)

Seth Lutske
Seth Lutske

Reputation: 10792

Create a featureGroup and add the markers to it:

const myGroup = L.featureGroup([node_10031, node_10032, node_10033]);

On whatever event you're using to capture the markers being added to the map, you can get the bounds of the featureGroup and set the map's bounds to that:

function onMarkersAddedEventHandler(){
  const bounds = myGroup.getBounds();
  map.fitBounds(bounds);
}

Now if you're saying that each marker has its own toggle in the UI, it's a bit more complicated. You'll have to attach an event to each marker's UI checkbox, and on change of that checkbox, add or remove the marker from the group, then reset the bounds:

const node_10031_checkbox = document.querySelector('input[type="checkbox"]#10031');

function onMarkersAddedEventHandler(e){
  if (e.target.checked){
    myGroup.addLayer(node_10031)
  } else {
    myGroup.removeLayer(node_10031)
  }
  const bounds = myGroup.getBounds();
  map.fitBounds(bounds);
}

Upvotes: 1

Related Questions