24

This is somewhat similar to the question asked here --

I'm writing a search box for a map application, which retrieves a whole set of search results (people's names & info) at once from a server and then pages through the list of results. So at any given point on the map there are two kinds of markers -- a background marker for points which are in the search results but not in the current page, and a foreground marker for points which are in the current page of search results.

All this works nicely.. what I'd like to do now is set it up so that if a user zooms or pans the map, the search results list updates to show only markers within the current map bounds.

Obviously there are server-side ways to do this, or I could also just run through the whole list of markers to see which fit within the current bounds; but does anybody know a built-in way to do this within leaflet? Something which would look like map.getVisibleLayers()?

Tim S
  • 371
  • 1
  • 2
  • 6

4 Answers4

20

I think this may be of help: https://github.com/stefanocudini/leaflet-list-markers

as you can see from the demo, including all markers in a layer, this plugin shows a list of only those visible in the current viewport. Its usage is simple, in a row:

var markersLayer = new L.LayerGroup();
map.addControl( new L.Control.ListMarkers({layer: markersLayer}) );

The code for obtain it is like as:

var layers = L.LayerGroup(), //layers contains all markers..
    contained = [];          //makers in map boundingbox

layers.eachLayer(function(l) {
    if( l instanceof L.Marker && map.getBounds().contains(l.getLatLng()) )
        contained.push(l);
});
stefcud
  • 2,220
  • 4
  • 27
  • 37
14

Here's a fully working function that does the job:

// var map is an instance of a Leaflet map
// this function assumes you have added markers as GeoJSON to the map
// it will return an array of all features currently shown in the
// active bounding region.

function getFeaturesInView() {
  var features = [];
  map.eachLayer( function(layer) {
    if(layer instanceof L.Marker) {
      if(map.getBounds().contains(layer.getLatLng())) {
        features.push(layer.feature);
      }
    }
  });
  return features;
}
auco
  • 9,329
  • 4
  • 47
  • 54
12

You have to check the bounds of each layer versus the map's bounds. Because eachLayer() returns all layers regardless of whether they are in the visible extent.

if(map.getBounds().contains(layer.getLatLng())) { ... }

In Stefano's code, this is shown around this line:

https://github.com/stefanocudini/leaflet-list-markers/blob/master/src/leaflet-list-markers.js#L95

Alex G Rice
  • 1,561
  • 11
  • 16
8

Regarding the last part of your question, if you want to iterate through visible layers, you can use eachLayer, e.g:

map.eachLayer(function (layer) {
    // do something with the layer
});

API reference: http://leafletjs.com/reference.html#map-stuff-methods

Tom
  • 688
  • 13
  • 29