Edit: Updated code after changes
I have a for loop that creates markers for a Google map. The problem I'm having is that I am creating some info windows (the bubbles that pop up when you click a location) that I need to integrate in the loop.
I currently have infowindow1 through 4 and contentMarker1 through 4 outside of the loop already defined. What I need is to tell the loop to use the correct one, which should be开发者_如何学Python easy since I have the i counter, but I can't get it to work, so I'm back at the start.
If someone can point me in the right direction with regards to pointing each marker towards the correct infowindow in the addListener I'd be very happy.
for (var i = 0; i < locations.length; i++) {
var beach = locations[i];
var myLatLng = new google.maps.LatLng(beach[1], beach[2]);
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
icon: image,
title: beach[0],
zIndex: beach[3],
animation: google.maps.Animation.DROP
});
google.maps.event.addListener(marker, 'click', (function(infoWindow) {
return function() {
alert(myLatLng[i]);
map.setZoom(9);
map.setCenter(myLatLng);
if (currentInfoWindow != null) {
currentInfoWindow.close();
}
infoWindow.open(map, marker);
currentInfoWindow = infoWindow;
}
})(infoWindow[i]));
}
If you want to reference a global variable using another variable to derive its name, you could do
window['infoWindow'+i]
which is exactly the same thing as
window.infoWindo1
when i = 1
, and all global variables reside on the window
object. Now, your variables may very well not be global, and honestly, regardless of whether or not they are, I don't think that code would be very neat.
It would certainly be preferable to keep your infowindows in an array, so that you may simply reference them as:
infoWindow[i]
Moving on, you'll also notice that the click listener for all the markers will trigger on a click, which occurs way after the loop has executed entirely, so the value of i
will aways be 4.
To work around this, you have to create a local scope for each click listener you're assigning, that encapsulates the value of the question as it is when the event is assigned:
google.maps.event.addListener(marker, 'click', (function(infoWin) {
return function() {
// your click listener here
// you can reference the current info window as infoWin
}
})(infoWindow[i]));
Possible way to do it by jquery...
// pass in a collection of data/ array
function initializeMap(data) {
//define map config... including start location
// set the marker for each location (recursive jquery function)
$.each(mapData.Details, function(i, location) {
setupLocationMarker(map, location);
});
}
// actual function used to display markers on the map
function setupLocationMarker(map, location) {
// create a marker
var latlng = new google.maps.LatLng(location.LatLng.Latitude, location.LatLng.Longitude);
var marker = new google.maps.Marker(latlng);
map.addOverlay(marker);
// add a marker click event
google.maps.Event.addListener(marker, "click", function(latlng) {
// open the info window with the location name
map.openInfoWindow(latlng, $("<b></b>").text(location.Name + " " + location.Postcode)[0]);
});
}
Instead of naming your info windows "infoWindow1", "infoWindow2", etc, make an array variable for your windows and then use indexes into that:
var infoWindow = [];
var contentMarker = [];
infoWindow[0] = ...
...
this will avoid the need for eval
or any other horrible way of choosing which window's variable has to be updated.
the problem you observe is called closure. The object google.maps.Marker
got an reference to the var beach
. At the time the member title
in google.maps.Marker
is accessed the most current beach
is requested wich is the last one.
The right way to solve this kind of problem is the so called immediate function:
for (var i = 0; i < locations.length; i++) {
var beach = locations[i];
var myLatLng = new google.maps.LatLng(beach[1], beach[2]);
var marker = (function (currentBeach) {
return new google.maps.Marker({
position: myLatLng,
map: map,
icon: image,
title: currentBeach[0],
zIndex: currentBeach[3],
animation: google.maps.Animation.DROP
});
}(beach))
// MARKERE START
google.maps.event.addListener(marker, 'click', function() {
map.setZoom(9); map.setCenter(myLatLng);
if (currentInfoWindow != null) {
currentInfoWindow.close();
}
infowindow.open(map, marker);
currentInfoWindow = infowindow;
});
}
BTW: The only thing which is able to define scope is the function
. So you should define the var
s at the beginning of the function in a single var
statement. This pattern is called single var statement pattern. :D
精彩评论