Thursday, February 27, 2014

Center Map on Layer Change in Leaflet

In Leaflet, it can be helpful to change the bounds of the map when the user adds or changes the visible map layers.

The Basics

First, we'll start with the initial code including our map and polygon layers:

  var circle = L.circle([51.508, -0.11], 500, {
      color: 'red',
      fillColor: '#f03',
      fillOpacity: 0.5
  });

  var polygon = L.polygon([
      [51.509, -0.08],
      [51.503, -0.06],
      [51.51, -0.047]
  ]);

  var map = L.map('map', {
    center: [51.505, -0.09],
    zoom: 13
  });

  var overlayMaps = {
    "Circle": circle,
    "Polygon": polygon
  };

  L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
  }).addTo(map);

  L.control.layers(overlayMaps, null, {
    collapsed: false
  }).addTo(map);

So far, most of this should be familiar from the Leaflet Quick Start Guide.

Next, we want to add a listener function that will zoom and re-center upon a change in the circle or polygon layer.

The .on method of map allows you to watch for an event to occur and then execute a function when it does. In this case, we want to wait for the event 'baselayerchange'. This way the map will automatically zoom and recenter when the user changes layers.


  map.on('baselayerchange', function(e) {
    console.log(e);
    map.fitBounds(e.layer);
  });


The map automatically zooms to the bounds of the shape when the layer is activated.

Options

There are a few options for exactly how the map is zoomed and/or re-centered and for what type of layers are affected.

If you want to do this with overlay layers instead of base layers, you can substitute 'overlayadd' for 'baselayerchange'. Using overlay layers is more common for drawing shapes, but treating your layers as base layers makes it easy to display only one at a time.

  map.on('overlayadd', function(e) {
    console.log(e);
    map.fitBounds(e.layer);
  });

fitBounds automatically zooms to the tightest zoom level where the whole shape is visible. If you don't want to use fitBounds (say you're centering on a new overlay layer and don't want to zoom all the way in), you can use setView or panTo instead. panTo animates as the view changes.

  map.on('overlayadd', function(e) {
    console.log(e);
    map.panTo(e.layer);
  });

And there you have a few different ways to center and/or zoom in when an overlay layer is added or when the baselayer is changed. I'd recommend you check out the documentation for fitBounds, setView, and panTo and play around with the options. The options for L.control.layers are also helpful. For example, you can set collapsed to false to encourage users to change the layers.

The full code is available in a gist.

References


1 comment: