Skip to content Skip to sidebar Skip to footer

Leafletjs Dynamically Bound Map To Visible Overlays

I am using leafletjs in my Rails app, adding the markers and using layer groups and overlays as 'categories'. I looked for examples and ideas on how I could bound/auto-zoom in and

Solution 1:

You can keep track of layers being added to and removed from the map using the layeradd and layerremove events. You'll need to build the bounds everytime one of your featuregroups gets added or removed. Working snippet with comments to elaborate:

var map = new L.Map('leaflet', {
    center: [0, 0],
    zoom: 0,
    layers: [
        new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            'attribution': 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors'
        })
    ]
});

map.on('layeradd layerremove', function () {
    // Create new empty bounds
    var bounds = new L.LatLngBounds();
    // Iterate the map's layers
    map.eachLayer(function (layer) {
        // Check if layer is a featuregroup
        if (layer instanceof L.FeatureGroup) {
            // Extend bounds with group's bounds
            bounds.extend(layer.getBounds());
        }
    });
    // Check if bounds are valid (could be empty)
    if (bounds.isValid()) {
        // Valid, fit bounds
        map.fitBounds(bounds);
    } else {
        // Invalid, fit world
        map.fitWorld();
    }
});

var markers = new L.FeatureGroup([
    new L.Marker([-30, -30]),
    new L.Marker([30, -30]),
    new L.Marker([-30, -60]),
    new L.Marker([30, -60])
]).addTo(map);

var polylines = new L.FeatureGroup([
    new L.Polyline([[-30, 30], [30, 60]]),
    new L.Polyline([[30, 30], [-30, 60]])
]).addTo(map);

var control = new L.Control.Layers(null, {
    'Markers': markers,
    'Polylines': polylines
}).addTo(map);
body {
    margin: 0;
}

html, body, #leaflet {
    height: 100%;
}
<!DOCTYPE html>
<html>
  <head>
    <title>Leaflet 1.0.3</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link type="text/css" rel="stylesheet" href="//unpkg.com/leaflet@1.0.3/dist/leaflet.css" />
  </head>
  <body>
    <div id="leaflet"></div>
    <script type="application/javascript" src="//unpkg.com/leaflet@1.0.3/dist/leaflet.js"></script>
  </body>
</html>

Hope that helps, good luck.


Solution 2:

If I understand correctly, you have some overlays (consulting and education Layer Groups) in a Layers Control, and you would like your map to automatically fit bounds of the visible markers whenever the user toggles one of these overlays.

Then the difficulty is that you need to retrieve the list of visible markers, so that you can compute their bounds and have the map adjust accordingly.

An easy solution would be to use Leaflet.FeatureGroup.SubGroup plugin, an intermediate "parent" Feature Group that will get the markers, and to replace your category Layer Groups by SubGroups from that plugin. This way, when added to the map, those SubGroups will actually add their child markers into the parent group. It then becomes trivial to get the bounds of all visible markers:

var parentGroup = L.featureGroup().addTo(map),
    subGroup1 = L.featureGroup.subGroup(parentGroup),
    subGroup2 = L.featureGroup.subGroup(parentGroup);

// Add your markers into the appropriate SubGroup…

var overlays = {
  'SubGroup 1': subGroup1,
  'SubGroup 2': subGroup2
};

L.control.layers(null, overlays).addTo(map);

// Have the map adjust view anytime the user uses the Layers Control overlays.
map.on('overlayadd overlayremove', function () {
  var bounds = parentGroup.getBounds();

  // Fit bounds only if the Parent Group actually has some markers,
  // i.e. it returns valid bounds.
  if (bounds.isValid()) {
    map.fitBounds(bounds);
  }
});

Demo: https://jsfiddle.net/3v7hd2vx/354/

Note that you no longer need your overall markers array to duplicate your markers into.

Disclaimer: I am the author of that plugin.


Post a Comment for "Leafletjs Dynamically Bound Map To Visible Overlays"