问题
I am creating a map for users on my website. The way it works is I use PHP and AJAX to get all the sites users addresses, I then pass these values to my JS as JSON where I generate a google map centered around the current users address with a marker for each user on the map. This part works at the moment but what I'm struggling with is generating a unique infowindow for each user. As it is right now I get the same info window for all markers, how can I fix this?
JS
jQuery(document).ready(function($){
$.ajax({
url: ajax_url,
type: 'post',
dataType: 'json',
data: {
action: 'map'
},
error : function(response){
console.log(response);
},
success : function(response){
var mapOptions = {
zoom: 16,
}
var geocoder = new google.maps.Geocoder();
var infowindow = new google.maps.InfoWindow();
// current user position
geocoder.geocode({'address': response.current[0].postcode}, function(results, status){
map.setCenter( results[0].geometry.location );
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
});
// other users loop
for( var i = 0; i < response.other.length; i++ ){
var postcode = response.other[i].postcode;
geocoder.geocode( {'address': postcode}, function(results, status){
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
google.maps.event.addListener(marker, 'click', function(){
infowindow.close(); // Close previously opened infowindow
infowindow.setContent( "<div id='infowindow'>"+ postcode +"</div>");
infowindow.open(map, this);
});
});
}
var map = new google.maps.Map(document.getElementById("buddy_map"), mapOptions);
return false;
}
});
});
PHP
add_action('wp_ajax_nopriv_map', 'addresses');
add_action('wp_ajax_map', 'addresses');
function addresses(){
global $current_user;
$address_street = get_user_meta( $current_user->ID, 'shipping_address_1', true );
$address_city = get_user_meta( $current_user->ID, 'shipping_city', true );
$address_postcode = get_user_meta( $current_user->ID, 'shipping_postcode', true );
$address = $address_street . ', ' . $address_city . ', ' . $address_postcode;
$cur_user[] = array(
"postcode" => $address
);
$other_users[] = array(
"postcode" => "LS11 6NA"
);
$other_users[] = array(
"postcode" => "LS11 6LY"
);
echo json_encode( array( "current" => $cur_user, "other" => $other_users) );
die();
}
I know my PHP file needs some work its just a rough draft to get this working first.
回答1:
You need to use a closure in your for
loop.
You can read Google documentation on Using closures in event listeners.
See the basic example below and note the use of the closure in the marker click event listener.
function initialize() {
var mapOptions = {
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: new google.maps.LatLng(1, 1)
};
var locations = [
[new google.maps.LatLng(0, 0), 'Marker 1', 'Infowindow content for Marker 1'],
[new google.maps.LatLng(0, 1), 'Marker 2', 'Infowindow content for Marker 2'],
[new google.maps.LatLng(0, 2), 'Marker 3', 'Infowindow content for Marker 3'],
[new google.maps.LatLng(1, 0), 'Marker 4', 'Infowindow content for Marker 4'],
[new google.maps.LatLng(1, 1), 'Marker 5', 'Infowindow content for Marker 5'],
[new google.maps.LatLng(1, 2), 'Marker 6', 'Infowindow content for Marker 6']
];
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var infowindow = new google.maps.InfoWindow();
for (var i = 0; i < locations.length; i++) {
var marker = new google.maps.Marker({
position: locations[i][0],
map: map,
title: locations[i][1]
});
google.maps.event.addListener(marker, 'click', (function (marker, i) {
return function () {
infowindow.setContent(locations[i][2]);
infowindow.open(map, marker);
}
})(marker, i));
}
}
#map-canvas {
height: 160px;
}
<div id="map-canvas"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initialize">
</script>
To illustrate with the use of the Geocoder, please see the below snippet. As I said in a comment, the Geocoder service has a QPS limit of 50 requests per second. If your locations list has more than 50 items, it is very likely that it will fail as the loop will be executed in less than 1 second.
function initialize() {
var geocoder = new google.maps.Geocoder();
var mapOptions = {
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: new google.maps.LatLng(40.718193, -74.001339)
};
var locations = [
['Marker 1', 'Infowindow content for Marker 1', '10001, USA'],
['Marker 2', 'Infowindow content for Marker 2', '10002, USA'],
['Marker 3', 'Infowindow content for Marker 3', '10003, USA'],
['Marker 4', 'Infowindow content for Marker 4', '10004, USA'],
['Marker 5', 'Infowindow content for Marker 5', '10005, USA'],
['Marker 6', 'Infowindow content for Marker 6', '10006, USA']
];
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var infowindow = new google.maps.InfoWindow();
for (var i = 0; i < locations.length; i++) {
geocoder.geocode({
'address': locations[i][2]
}, (function(locations, i) {
return function(results, status) {
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
title: locations[i][0]
});
google.maps.event.addListener(marker, 'click', (function(marker) {
return function() {
infowindow.setContent("<div id='infowindow-content'><h3>" + locations[i][1] + "</h3>" + results[0]['formatted_address'] + "</div>");
infowindow.open(map, marker);
}
})(marker));
}
})(locations, i));
}
}
#map-canvas {
height: 160px;
}
<div id="map-canvas"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initialize">
</script>
来源:https://stackoverflow.com/questions/56869829/google-maps-multiple-markers-with-unique-infowindows