5

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!

Ganberry
  • 79
  • 1
  • 8

1 Answers1

6

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);
}
Alex Morega
  • 4,132
  • 1
  • 24
  • 25
  • Thanks a ton, Alex! I haven't plugged it in yet, but this looks great. I appreciate the extra tips. One issue I sometimes have when reading tutorials/examples is that they don't always show the full function (which makes sense given that every situation is different), and things like fitBounds and LatLngBounds end up not playing nice with the rest of my stuff. I'm not yet skilled enough to troubleshoot everything myself, though I try! – Ganberry May 23 '15 at 17:28
  • Do you know what it means when I get leaflet.js errors? Such as "TypeError: o.DomUtil.getPosition(...) is undefined" or "TypeError: this._startPos is undefined" or "TypeError: this._northEast is undefined". I'm using leaflet-0.7.3 from cdn. – Ganberry May 23 '15 at 21:45
  • Set up an example that illustrates your problem, otherwise it's impossible to guess. – Alex Morega May 24 '15 at 08:06
  • It happens when I use your example. And any time I use fitBounds or get LatLng or LatLngBounds. My guess would be that it can't figure out where the edges of the bounds are. Possibly related: https://stackoverflow.com/questions/17277686/leaflet-js-center-the-map-on-a-group-of-markers – Ganberry May 24 '15 at 16:50