lito
lito

Reputation: 3125

setTimeout() and dropping markers on google map

I don't understand why setTimeout is not working as I expected.

I want to drop each marker on a different time, not all at the same time.

Paste and run this code into http://jsfiddle.net, then remove comments in order to see the funny behavior:

        //setTimeout(function() {
            addMarker(m);
        //}, i * 500);

.

<link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="//maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
  var berlin = new google.maps.LatLng(52.520816, 13.410186);
  var neighborhoods = [
    new google.maps.LatLng(52.511467, 13.447179),
    new google.maps.LatLng(52.549061, 13.422975),
    new google.maps.LatLng(52.497622, 13.396110),
    new google.maps.LatLng(52.517683, 13.394393)
  ];
  var map;
  function initialize() {
    var mapOptions = {
      zoom: 12,
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      center: berlin
    };
    map = new google.maps.Map(document.getElementById("map_canvas"),mapOptions);
  }

  function drop() {
    var j = 0;
    for (var i = 0; i < neighborhoods.length; i++) {
        var m = neighborhoods[i];
        //setTimeout(function() {
            addMarker(m);
        //}, i * 500);
    }
  }
  function addMarker(m) {
    new google.maps.Marker({
      position: m,
      map: map,
      draggable: false,
      animation: google.maps.Animation.DROP
    });
  }
</script>
<body onload="initialize()">
<div id="map_canvas" style="width: 500px; height: 400px;">map div</div>
<button id="drop" onclick="drop()">Drop Markers</button>
</body>

Upvotes: 1

Views: 5435

Answers (3)

Zeta
Zeta

Reputation: 105885

The problem is your iteration over the neighborhoods and the locale variable var m = neighborhoods[i]. The value of m, which is used in addMarker(m) is replaced by the very last element in neighborhoods, which will result in all markers drop on the same spot.

Use the following code instead (JSFiddle). It iterates over a global counter, which you could replace by a static variable and sets an interval instead of a timeout:

  var droppedCount = 0;
  var droppedInterval = null;

  function drop() {
    if(droppedCount === neighborhoods.length){
        clearInterval(droppedInterval);
        return;
    }
    else if(droppedInterval === null)
        droppedInterval = setInterval(drop,500);

    var m = neighborhoods[droppedCount++];
    addMarker(m);
  }

Upvotes: 2

mfeineis
mfeineis

Reputation: 2657

The problem is that the function in the setTimeout closes over the variable m, not the current value of it at time of creation. The solution should be:

// ...
var m = neighborhoods[i];
(function (myMarker) {
setTimeout(function() {
    addMarker(myMarker );
}, i * 500);
}(m));
// ...

Upvotes: 1

Mark Holland
Mark Holland

Reputation: 846

It's because the value of 'm' has changed long before the timeOut event triggers.

You should wrap this code in a closure so as to capture the value of m.

Something like:

for (var i = 0; i < neighborhoods.length; i++) {
    var m = neighborhoods[i];

    (function(n){
      setTimeout(function() {
        addMarker(n);
     }, i * 500);
   }(m));
}

Upvotes: 7

Related Questions