Ganberry
Ganberry

Reputation: 89

Zoom to fit leaflet.js markers

I'm converting my site from google maps to leaflet/openstreetmap. On the site, search results show up as markers on a map. Results can have one marker, or 10, or 200. That's all fine and great. But when the results have multiple markers, I'm having trouble getting it to zoom/fit all of them. Instead, it just zooms in on one (probably because I have the zoom in map.setView to 18!).

In my case, is there an alternative to using map.setView? I don't want to set the zoom to 18 in all cases; but would like the zoom simply fit the contents. I know there are some similar questions on SO, but they don't help as I don't know how to replace withe map.setView with something that doesn't hardcode the zoom. Here's my entire function:

function showLocations(ids, lats, lons, contents) {
  locationIDs = ids;
  infoWindows = new Array();
  markers = new Array();

  map = new L.Map('map_canvas');
  var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
  var osmAttrib='Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors';
  var osm = new L.TileLayer(osmUrl, {minZoom: 1, maxZoom: 19, attribution: osmAttrib});

  for (i in ids) {

    var infoWindow = L.popup()
    .setContent(contents[i]);   

    map.setView(new L.LatLng(lats[i], lons[i]),18);
    map.addLayer(osm);
    L.marker([lats[i], lons[i]]).addTo(map)
    .bindPopup(infoWindow)
    .openPopup();

  }
}

With google maps, I use this:

markers.push(marker);
bounds.extend(latlng);

if (contents.length === 1) {
  map.setZoom(18);
  map.setCenter(new google.maps.LatLng(lats[0], lons[0]));
} else {
  map.fitBounds(bounds);
}

Thanks!

Upvotes: 5

Views: 5266

Answers (1)

Alex Morega
Alex Morega

Reputation: 4228

Leaflet also has a LatLngBounds class, with an extend method, and the map has a fitBounds method, so you could port the Google Maps code 1:1.

A few more points: there's no need to call map.addLayer(osm) inside the loop, calling it once is enough; it's good practice to add var to all your variables; and for (i in ids) is a dangerous way to iterate over an array, better call ids.forEach.

function showLocations(ids, lats, lons, contents) {
  var infoWindows = new Array();
  var markers = new Array();

  var map = new L.Map('map_canvas');
  var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
  var osmAttrib='Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors';
  var osm = new L.TileLayer(osmUrl, {minZoom: 1, maxZoom: 19, attribution: osmAttrib});
  map.addLayer(osm);

  var bounds = new L.LatLngBounds();

  ids.forEach(function(i) {
    var infoWindow = L.popup().setContent(contents[i]);

    var marker = L.marker([lats[i], lons[i]])
      .addTo(map)
      .bindPopup(infoWindow)
      .openPopup();

    bounds.extend(marker.getLatLng());
  });

  map.fitBounds(bounds);
}

Upvotes: 6

Related Questions