gwaters
gwaters

Reputation: 43

Google Maps API v3 binding events to multiple maps

I've got a page with two Google maps on, using the v3 API. Currently they have one pin each, with the same lat & long set for each pin, although one of the maps will have other pins added at a later date (when I can get this to work!) The maps are generated by looping through an object, so further maps can be added simply if needed.

What I am trying to do is bind the bounds_changed event once to both maps, to run map.setZoom() after map.fitBounds() has been run. The event, however, only binds to the last map to be set up, so does not reset the zoom on the first map.

Link to JSFiddle replicating the issue: http://jsfiddle.net/pkhb8mvz/7/

(For a more clear example of what the event is being bound to, change the event to listen on click rather than bounds_changed then try clicking on the first map and watch the zoom level change on the second map)

Any help greatly appreciated!

Upvotes: 2

Views: 980

Answers (3)

geocodezip
geocodezip

Reputation: 161334

You can't add a listener to multiple maps unless you keep references to all of them, currently you are only keeping a reference to the last map created.

    // use function closure to associate the map with its bounds listener
    addBoundsListener(map, opts, bounds);
    map.fitBounds(bounds);
}

function addBoundsListener(map, opts, bounds) {
    // If no center option has been specified, center the map to
    // contain all pins and reset the zoom
    var listener = new google.maps.event.addListenerOnce(map, "bounds_changed", function () {
        if (!opts.center) {
            map.setZoom(opts.zoom);
        }
    });
}

updated fiddle

code snippet:

var maps = {
  "propertyLocation": {
    "mapElement": "#map1",
    "options": {
      "zoom": 10,
      "streetViewControl": false
    },
    "pins": [{
      "title": "Test 1",
      "lat": "52.1975331616",
      "long": "0.9771180153"
    }]
  },
  "localArea": {
    "mapElement": "#map2",
    "options": {
      "zoom": 14,
      "streetViewControl": false
    },
    "pins": [{
      "title": "Test 2",
      "lat": "52.1975331616",
      "long": "0.9771180153"
    }]
  }
};

// Sensible defaults
var defaults = {
  zoom: 9,
  mapTypeId: google.maps.MapTypeId.ROADMAP,
  draggable: true
};

for (var i in maps) {
  // Extend the options
  var opts = $.extend(true, defaults, maps[i].options),
    marker,
    map,
    bounds = new google.maps.LatLngBounds();

  // Create the map
  map = new google.maps.Map($(maps[i].mapElement)[0], opts);

  // Create all pins
  for (var p = 0; p < maps[i].pins.length; p++) {
    var pin = maps[i].pins[p];
    marker = new google.maps.Marker({
      position: new google.maps.LatLng(pin.lat, pin.long),
      map: map,
      title: pin.title,
      icon: pin.icon
    });

    // Extend the bounds of the map to contain the marker
    bounds.extend(marker.position);
  }
  // use function closure to associate the map with its bounds listener
  addBoundsListener(map, opts, bounds);
  map.fitBounds(bounds);
}

function addBoundsListener(map, opts, bounds) {
  // If no center option has been specified, center the map to
  // contain all pins and reset the zoom
  var listener = new google.maps.event.addListenerOnce(map, "bounds_changed", function() {
    if (!opts.center) {
      map.setZoom(opts.zoom);
    }
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://maps.googleapis.com/maps/api/js?libraries=places&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div style="width: 500px; height: 500px;" id="map1"></div>
<div style="width: 500px; height: 500px;" id="map2"></div>

Upvotes: 0

tomcant
tomcant

Reputation: 26

The problem is that the map variable is being redefined on each iteration of your loop, so by the time your event listener callback runs it will operate on the second google.maps.Map object. The simplest solution is to capture the value of the map variable on each iteration using a closure, like so:

(function (map) {
    var listener = new google.maps.event.addListenerOnce(map, "bounds_changed", function () {
        if (!opts.center) {
            map.setZoom(opts.zoom);
        };
    });
}) (map);

I forked your JSFiddle to demonstrate the idea: https://jsfiddle.net/e8qbr8qL/

Upvotes: 1

codegaze
codegaze

Reputation: 755

Created this fiddle that works based on this answer https://stackoverflow.com/a/5839041/2321666.

Apart from the function you need to add, your map variable should be an array so that there is one instance of each map.

map[i] = new google.maps.Map($(maps[i].mapElement)[0], opts);

If you need any explanation of the code please ask, but i think there is enough info about javascript closures in the post added.

Upvotes: 0

Related Questions