将 actionListeners 添加到动态创建的 google 标记以绘制路线

Adding actionListeners to dynamically created google markers to plot routes

我有一个页面可以从数据库中检索一些位置,并根据它们 lat/long 创建标记以显示在地图上。标记保存在一个数组中,我使用 for 循环将 onclick 动作侦听器分配给每个标记。当用户单击标记时,我希望显示从他们当前位置到标记位置的路线。我遇到的问题是,无论单击哪个标记,它总是绘制一条通往数组中最后一个标记的路径。

这就是地图的样子

在上面的示例中,我将单击红色标记 A。

如您所见,它已经绘制了一条通往标记 D 的航线。

我的代码:

   //THIS FUNCTIONS BUILD THE MAPS
function initializeMap(position) 
{       //USER LOCATION
        var myCenter = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);

         var mapProp =
                {
                    center: myCenter,
                    zoom: 13,
                    mapTypeId: google.maps.MapTypeId.ROADMAP
                };
        mapObj = new google.maps.Map(document.getElementById("googleMap"), mapProp);

        //MAKING SURE THE DATA ARRAY HAS SOMETHING IN IT
        if (ajaxResult.length > 0)
        {
            for (var i = 0; i < ajaxResult.length; i++)
            {
                var pos = {lat: parseFloat(ajaxResult[i][6]), lng: parseFloat(ajaxResult[i][7])};
                //BUILDING THE DESTINATION MARKERS
                var suggestionMarker = new google.maps.Marker({
                    position: pos,
                    icon: markerNames[i]
                }); 

                markers.push(suggestionMarker);//ADDING TO THE MARKER ARRAY
                suggestionMarker.setMap(mapObj);//ADING TO THE MAP

                var userString = ajaxResult[i][1];//INFORMATINO WINDOW
                var infowindow = new google.maps.InfoWindow({
                    content: userString
                });
                infowindow.open(mapObj, suggestionMarker);
            }
            addMarkerListeners(myCenter);
        }

        //MARKER FOR THE USER LOCATION
        var userImage = 'assets/img/GoogleMapsMarkers/blue_MarkerA.png'
        var userMarker = new google.maps.Marker({
            position: myCenter,
            icon: userImage
        });
        markers.push(userMarker);

        userMarker.setMap(mapObj);

        //USER INFORMATION WINDOW
        var userString = "You!";
        var infowindow = new google.maps.InfoWindow({
            content: userString
        });
        infowindow.open(mapObj, userMarker);
    }

    /*
     * 
     * @param {type} option
     * @returns {Boolean}
     * ACCEPTS THE USER LOCATION AND ADDS ACTION LISTENERS TO EACH MARKER
     * IN THE MARKER ARRAY. THE ACTION LISTENER CALLS THE PLOT ROUTE
     * FUNCTION AND PASSES IT THE MARKER POSITION AND USER POSITION
     */
    function addMarkerListeners(myCenter)
    {
        if(markers.length > 0)
        {
            for(var i = 0; i < markers.length-1; i++)
            {
                google.maps.event.addListener(markers[i],'click', function(){plotRoute(markers[i].getPosition(),myCenter);});
                //markers[i].addEventListener('click', function(){plotRoute(markers[i].getPosition(),myCenter);});
                directionsDisplay.setMap(mapObj);
            }
        }
    }

    //CREATES A ROUT
    function plotRoute(pos, myCenter)
    {
        var request = {
            origin: myCenter,
            destination: pos,
            travelMode: 'DRIVING'
        };

        directionsService.route(request, function(result,status){
            if(status === 'OK')
            {
                directionsDisplay.setDirections(result);
            }
        });
    }

请注意,实际的最终标记始终是用户标记,但指示 for 循环不包含它。谁能看出为什么它只在标记数组中绘制到最终目的地标记的路线?

这是循环设置事件侦听器的常见问题。它在这个相关问题中得到解决:Google Maps JS API v3 - Simple Multiple Marker Example using function closure。要在您的代码中使用该解决方案:

function addMarkerListeners(myCenter) {
  if (markers.length > 0) {
    for (var i = 0; i < markers.length; i++) {

      // function closure on the "i" variable
      google.maps.event.addListener(markers[i], 'click', (function(i) {
      return function() {
        plotRoute(markers[i].getPosition(), myCenter);
      }})(i));

      directionsDisplay.setMap(mapObj);
    }
  }
}

proof of concept fiddle

为了不关闭函数解决它,你可以在事件处理函数中使用this,它指的是被点击的标记:

function addMarkerListeners(myCenter) {
  if (markers.length > 0) {
    for (var i = 0; i < markers.length; i++) {
      google.maps.event.addListener(markers[i], 'click', function() {
        plotRoute(this.getPosition(), myCenter);
      });
      directionsDisplay.setMap(mapObj);
    }
  }
}

proof of concept fiddle

代码片段(使用函数闭包):

var geocoder;
var map;
var markers = [];
var directionsDisplay = new google.maps.DirectionsRenderer();
var directionsService = new google.maps.DirectionsService();

function initialize() {
// Googleplex 37.4223434, -122.0843689
    var position = {coords: {latitude:37.4223434, longitude:-122.0843689}}
    initializeMap(position);

}
google.maps.event.addDomListener(window, "load", initialize);

// Menlo Park, CA, USA (37.4529598, -122.18172520000002)
// Mountain View, CA, USA (37.3860517, -122.0838511)
var ajaxResult = [[0,"infowindow 0",2,3,4,5,37.4419,-122.1419],
[1,"infowindow 1",2,3,4,5,37.4529598,-122.1817252],[2,"infowindow 2",2,3,4,5,37.3860517,-122.0838511]]
//THIS FUNCTIONS BUILD THE MAPS
function initializeMap(position) { //USER LOCATION
  var myCenter = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);

  var mapProp = {
    center: myCenter,
    zoom: 13,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  mapObj = new google.maps.Map(document.getElementById("googleMap"), mapProp);

  //MAKING SURE THE DATA ARRAY HAS SOMETHING IN IT
  if (ajaxResult.length > 0) {
    for (var i = 0; i < ajaxResult.length; i++) {
      var pos = {
        lat: parseFloat(ajaxResult[i][6]),
        lng: parseFloat(ajaxResult[i][7])
      };
      //BUILDING THE DESTINATION MARKERS
      var suggestionMarker = new google.maps.Marker({
        position: pos,
        // icon: markerNames[i]
      });

      markers.push(suggestionMarker); //ADDING TO THE MARKER ARRAY
      suggestionMarker.setMap(mapObj); //ADING TO THE MAP

      var userString = ajaxResult[i][1]; //INFORMATINO WINDOW
      var infowindow = new google.maps.InfoWindow({
        content: userString
      });
      infowindow.open(mapObj, suggestionMarker);
    }
    addMarkerListeners(myCenter);
  }

  //MARKER FOR THE USER LOCATION
  var userImage = 'http://maps.google.com/mapfiles/ms/micons/blue.png'
  var userMarker = new google.maps.Marker({
    position: myCenter,
    icon: userImage
  });
  markers.push(userMarker);

  userMarker.setMap(mapObj);

  //USER INFORMATION WINDOW
  var userString = "You!";
  var infowindow = new google.maps.InfoWindow({
    content: userString
  });
  infowindow.open(mapObj, userMarker);
}

/*
 * 
 * @param {type} option
 * @returns {Boolean}
 * ACCEPTS THE USER LOCATION AND ADDS ACTION LISTENERS TO EACH MARKER
 * IN THE MARKER ARRAY. THE ACTION LISTENER CALLS THE PLOT ROUTE
 * FUNCTION AND PASSES IT THE MARKER POSITION AND USER POSITION
 */
function addMarkerListeners(myCenter) {
  if (markers.length > 0) {
    for (var i = 0; i < markers.length; i++) {
      google.maps.event.addListener(markers[i], 'click', (function(i) {
      return function() {
        plotRoute(markers[i].getPosition(), myCenter);
      }})(i));
      directionsDisplay.setMap(mapObj);
    }
  }
}

//CREATES A ROUTE
function plotRoute(pos, myCenter) {
  var request = {
    origin: myCenter,
    destination: pos,
    travelMode: 'DRIVING'
  };

  directionsService.route(request, function(result, status) {
    if (status === 'OK') {
      directionsDisplay.setDirections(result);
    } else alert("directions request failed: "+status);
  });
}
html,
body,
#googleMap {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="googleMap"></div>

代码片段(使用this):

var geocoder;
var map;
var markers = [];
var directionsDisplay = new google.maps.DirectionsRenderer();
var directionsService = new google.maps.DirectionsService();

function initialize() {
// Googleplex 37.4223434, -122.0843689
    var position = {coords: {latitude:37.4223434, longitude:-122.0843689}}
    initializeMap(position);

}
google.maps.event.addDomListener(window, "load", initialize);

// Menlo Park, CA, USA (37.4529598, -122.18172520000002)
// Mountain View, CA, USA (37.3860517, -122.0838511)
var ajaxResult = [[0,"infowindow 0",2,3,4,5,37.4419,-122.1419],
[1,"infowindow 1",2,3,4,5,37.4529598,-122.1817252],[2,"infowindow 2",2,3,4,5,37.3860517,-122.0838511]]
//THIS FUNCTIONS BUILD THE MAPS
function initializeMap(position) { //USER LOCATION
  var myCenter = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);

  var mapProp = {
    center: myCenter,
    zoom: 13,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  mapObj = new google.maps.Map(document.getElementById("googleMap"), mapProp);

  //MAKING SURE THE DATA ARRAY HAS SOMETHING IN IT
  if (ajaxResult.length > 0) {
    for (var i = 0; i < ajaxResult.length; i++) {
      var pos = {
        lat: parseFloat(ajaxResult[i][6]),
        lng: parseFloat(ajaxResult[i][7])
      };
      //BUILDING THE DESTINATION MARKERS
      var suggestionMarker = new google.maps.Marker({
        position: pos,
        // icon: markerNames[i]
      });

      markers.push(suggestionMarker); //ADDING TO THE MARKER ARRAY
      suggestionMarker.setMap(mapObj); //ADING TO THE MAP

      var userString = ajaxResult[i][1]; //INFORMATINO WINDOW
      var infowindow = new google.maps.InfoWindow({
        content: userString
      });
      infowindow.open(mapObj, suggestionMarker);
    }
    addMarkerListeners(myCenter);
  }

  //MARKER FOR THE USER LOCATION
  var userImage = 'http://maps.google.com/mapfiles/ms/micons/blue.png'
  var userMarker = new google.maps.Marker({
    position: myCenter,
    icon: userImage
  });
  markers.push(userMarker);

  userMarker.setMap(mapObj);

  //USER INFORMATION WINDOW
  var userString = "You!";
  var infowindow = new google.maps.InfoWindow({
    content: userString
  });
  infowindow.open(mapObj, userMarker);
}

/*
 * 
 * @param {type} option
 * @returns {Boolean}
 * ACCEPTS THE USER LOCATION AND ADDS ACTION LISTENERS TO EACH MARKER
 * IN THE MARKER ARRAY. THE ACTION LISTENER CALLS THE PLOT ROUTE
 * FUNCTION AND PASSES IT THE MARKER POSITION AND USER POSITION
 */
function addMarkerListeners(myCenter) {
  if (markers.length > 0) {
    for (var i = 0; i < markers.length; i++) {
      google.maps.event.addListener(markers[i], 'click', function() {
        plotRoute(this.getPosition(), myCenter);
      });
      directionsDisplay.setMap(mapObj);
    }
  }
}

//CREATES A ROUT
function plotRoute(pos, myCenter) {
  var request = {
    origin: myCenter,
    destination: pos,
    travelMode: 'DRIVING'
  };

  directionsService.route(request, function(result, status) {
    if (status === 'OK') {
      directionsDisplay.setDirections(result);
    }
  });
}
html,
body,
#googleMap {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="googleMap"></div>