1

Given a set of existing Marker locations on a Google Maps view, how can I add the points to a PolyLine overlay?

I'm building a web tour application where the user is able to select the stop locations based on a set of GPS coordinates retrieved via an AJAX call. This part works fine, as all the points are showing on the map.

My issue is I want to add ONLY the marker locations to the polyline. Currently the points selected are added to a tourList array, which is converted to a JSON array and posted via a jquery ajax post call. So I know the click event handlers are working for one part.

This question almost fits my needs, except is it intended for Maps API v2, and I'm using V3.

What I've gotten so far:

//page-specific global variables
var visitPoints = new google.maps.MVCArray();
var polyLine;
var map;

window.onload= function(){
  //set initial map location
  map = new google.maps.Map(
    document.getElementById("map"), mapOptions);    

  //set up polyline capability
  var polyOptions = new google.maps.Polyline({
    path: visitPoints,
    map: map
  });

  polyLine = new google.maps.Polyline(polyOptions);
  polyLine.setMap(map); 

  //get all the GPS locations in the database  This function and makeMarkers works 
  //as designed
  var request = $.ajax({
    type:"GET",
    url: "includes/phpscripts.php?action=cords",
    dataType:"json",
    success: makeMarkers
  });

  //Populate the map view with the locations and save tour stops in array
  function makeMarkers(response){
    console.log("Response Length: "+response.length)
    for (var i=0; i< response.length; i++){
      var marker= new google.maps.Marker({
        position: new google.maps.LatLng(response[i].lat, response[i].lon),
        map: map,
        title: response[i].fileName
      });

      //anonymous function wrapper to create distinct markers
      (function(marker){
        google.maps.event.addListener(marker, 'click', function(){

          tourList.push(marker); //add marker to tour list
          visitPoints.push(marker.latlng); //add location to polyline array
          console.log("Tour List length- # stops: "+tourList.length);

        });
      })(marker);    
    }
  }

  //listener for poline click
  google.maps.event.addListener(map, 'click', updatePolyline)

} //end onload function

//updates the polyline user selections
function updatePolyline(event){
  var path = polyLine.getPath();
  path.push(event.latlng);
} //end updatePolyline

Currently, I'm not getting any script warnings in Firebug, but the updatePolyline function is never called.

Do I need to add a listener inside the marker listener to update the polyline?

Community
  • 1
  • 1
Jason
  • 11,263
  • 21
  • 87
  • 181

1 Answers1

2

You wrote "I want to add ONLY the marker locations to the polyline" though the way the code is setup, the polyline gets a new vertex added everytime a marker is clicked, or a blank part of the map is clicked. For the polyline to be updated by itself it has to be outside a listener.

There were two places that needed to be changed,

 visitPoints.push(marker.latlng);

to marker.getPosition()

And event.latlng near the end to event.latLng (capital L for Lng).

I ran into some difficulty while testing. The docs describe auto-updating when an MVCArray is assigned to the Polyline path; however, it appears that the Polyline doesn't like an uninitialized MVCArray (empty visitPoints). The auto-updating wasn't happening when I clicked on the markers.

Only when I set it with an initial LatLng it worked as expected, but I ended up ditching visitPoints because it is unknown where the first point will be. I suppose the best approach is to initialize the Polyline with a MVCArray visitPoints when the Ajax returns. The demo below uses getPath, push instead of visitPoints.

DEMO http://jsfiddle.net/yV6xv/8/ (Click on markers or map for line updates)

A dirty hack to get visitPoints initialized so the rest of the code functions as expected, plus some minor changes to marker.latlng and event.latlng. The first click will define the line's first point, and subsequent clicks extend the line.

there must be a better way

DEMO http://jsfiddle.net/yV6xv/9/

//page-specific global variables
var visitPoints = new google.maps.MVCArray();
var polyLine;
var map;

// REDEFINING mapOptions and tourList
var mapOptions = { center: new google.maps.LatLng(0.0, 0.0), zoom: 2,
        mapTypeId: google.maps.MapTypeId.ROADMAP};
var tourList = [];

window.onload= function(){
  //set initial map location
  map = new google.maps.Map(
    document.getElementById("map"), mapOptions);    

  //initialization hack
  visitPoints.push(new google.maps.LatLng(0,0));

  //set up polyline capability
  var polyOptions = new google.maps.Polyline({
    path: visitPoints,
    map: map
  });

  //complete initialization hack
  visitPoints.pop();

  polyLine = new google.maps.Polyline(polyOptions);
  polyLine.setMap(map); 

  //get all the GPS locations in the database  This function and makeMarkers works 

/* TEMPORARY COMMENTING OUT
  //as designed
  var request = $.ajax({
    type:"GET",
    url: "includes/phpscripts.php?action=cords",
    dataType:"json",
    success: makeMarkers
  });
*/

makeMarkers([{lat:0, lon:0},{lat:10, lon:10},{lat:15, lon:20},{lat:20, lon:30}]);


  //Populate the map view with the locations and save tour stops in array
  function makeMarkers(response){
    console.log("Response Length: "+response.length)
    for (var i=0; i< response.length; i++){
      var marker= new google.maps.Marker({
        position: new google.maps.LatLng(response[i].lat, response[i].lon),
        map: map,
        title: response[i].fileName
      });

      //anonymous function wrapper to create distinct markers
      (function(marker){
        google.maps.event.addListener(marker, 'click', function(){

          tourList.push(marker); //add marker to tour list
          visitPoints.push(marker.getPosition()); //add location to polyline array
          console.log("Tour List length- # stops: "+tourList.length);

        });
      })(marker);    
    }
  }

  //listener for poline click
  google.maps.event.addListener(map, 'click', updatePolyline)

} //end onload function

//updates the polyline user selections
function updatePolyline(event){
  var path = polyLine.getPath();
  path.push(event.latLng);
} //end updatePolyline
Tina CG Hoehr
  • 6,721
  • 6
  • 44
  • 57
  • This is the solution, thanks for the help! Why is there no MVCArray needed for the polyline points, though? From the examples given, it was necessary to have some place to store the locations in the line. – Jason Jun 07 '12 at 17:43
  • I always use a plain array of LatLngs to store coordinates for lines and polygons and this was the first time I got to work with an MVCArray. I guess I'm not all up-to-speed with all the available tools :( I do recommend using the MVCArray because it's less coding to get the line updated. Since I lack experience, the only way I got the line to work with MVCArray was to have it include at least one LatLng before being assigned to the Polyline. Perhaps there's a good example that shows how it should be initialized properly. – Tina CG Hoehr Jun 07 '12 at 18:08
  • I wasn't too happy leaving the MVCArray like that so I came up with a hack. (details in the updated answer above). It turns out you can initialize the polyline with an arbitrary point, then pop (remove) the point so it acts as it's empty, and works with the rest of your code. I figured this is allowed because I was calling getPath() on the empty polyline. I suspect that internally MVCArray keeps track of what the content type is, but it doesn't know anything when `new MVCArray` is called. That's my best guess. – Tina CG Hoehr Jun 07 '12 at 19:01
  • This solution worked, but one issue is that any click event results in the PolyLine extended to the click point. So, I created a list of points from the response object and compared the click location to existing markers in the updatePolyline function. This way, only valid marker locations are added to the polyline path. – Jason Jun 11 '12 at 14:31
  • Got it, I wasn't sure what to do and left options open. I understood the map listener was meant to extend the polyline. – Tina CG Hoehr Jun 11 '12 at 22:05