I have several markers on a map with polylines drawn. I would like to move each marker along the path of the polyline to simulate simultaneous movement of each marker.
I am having problems doing this I am getting only the last marker to move and the rest doesn't. Being new to the use of this programming technology I think something is wrong with my code especially the way I attempt to animate each marker. I need some guidance on this.
Here's my work thus far: Jsbin DEMO
var startLoc = new Array();
startLoc[0] = 'rio claro, trinidad';
startLoc[1] = 'preysal, trinidad';
startLoc[2] = 'san fernando, trinidad';
startLoc[3] = 'couva, trinidad';
var endLoc = new Array();
endLoc[0] = 'princes town, trinidad';
endLoc[1] = 'tabaquite, trinidad';
endLoc[2] = 'mayaro, trinidad';
endLoc[3] = 'arima, trinidad';
var Colors = ["#FF0000", "#00FF00", "#0000FF"];
function initialize() {
infowindow = new google.maps.InfoWindow(
{
size: new google.maps.Size(150,50)
});
var myOptions = {
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
address = 'Trinidad and Tobago'
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
map.setCenter(results[0].geometry.location);
});
}
function createMarker(latlng, label, html) {
// alert("createMarker("+latlng+","+label+","+html+","+color+")");
var contentString = '<b>'+label+'</b><br>'+html;
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: label,
zIndex: Math.round(latlng.lat()*-100000)<<5
});
marker.myname = label;
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map,marker);
});
return marker;
}
function setRoutes(){
var directionsDisplay = new Array();
for (var i=0; i< startLoc.length; i++){
var rendererOptions = {
map: map,
suppressMarkers : true
}
directionsService = new google.maps.DirectionsService();
var travelMode = google.maps.DirectionsTravelMode.DRIVING;
var request = {
origin: startLoc[i],
destination: endLoc[i],
travelMode: travelMode
};
directionsService.route(request,makeRouteCallback(directionsDisplay[i]));
}
function makeRouteCallback(disp){
return function(response, status){
if (status == google.maps.DirectionsStatus.OK){
var bounds = new google.maps.LatLngBounds();
var route = response.routes[0];
startLocation = new Object();
endLocation = new Object();
polyline = new google.maps.Polyline({
path: [],
strokeColor: '#FFFF00',
strokeWeight: 3
});
poly2 = new google.maps.Polyline({
path: [],
strokeColor: '#FFFF00',
strokeWeight: 3
});
// For each route, display summary information.
var path = response.routes[0].overview_path;
var legs = response.routes[0].legs;
//Routes
if (status == google.maps.DirectionsStatus.OK){
console.log(response);
disp = new google.maps.DirectionsRenderer(rendererOptions);
disp.setMap(map);
disp.setDirections(response);
//Markers
for (i=0;i<legs.length;i++) {
if (i == 0) {
startLocation.latlng = legs[i].start_location;
startLocation.address = legs[i].start_address;
// marker = google.maps.Marker({map:map,position: startLocation.latlng});
marker = createMarker(legs[i].start_location,"start",legs[i].start_address,"green");
}
endLocation.latlng = legs[i].end_location;
endLocation.address = legs[i].end_address;
var steps = legs[i].steps;
for (j=0;j<steps.length;j++) {
var nextSegment = steps[j].path;
var nextSegment = steps[j].path;
for (k=0;k<nextSegment.length;k++) {
polyline.getPath().push(nextSegment[k]);
//bounds.extend(nextSegment[k]);
}
}
}
}
}
polyline.setMap(map);
//map.fitBounds(bounds);
startAnimation();
}
}
}
var lastVertex = 1;
var stepnum=0;
var step = 50; // 5; // metres
var tick = 100; // milliseconds
var eol;
//----------------------------------------------------------------------
function updatePoly(d) {
// Spawn a new polyline every 20 vertices, because updating a 100-vertex poly is too slow
if (poly2.getPath().getLength() > 20) {
poly2=new google.maps.Polyline([polyline.getPath().getAt(lastVertex-1)]);
// map.addOverlay(poly2)
}
if (polyline.GetIndexAtDistance(d) < lastVertex+2) {
if (poly2.getPath().getLength()>1) {
poly2.getPath().removeAt(poly2.getPath().getLength()-1)
}
poly2.getPath().insertAt(poly2.getPath().getLength(),polyline.GetPointAtDistance(d));
} else {
poly2.getPath().insertAt(poly2.getPath().getLength(),endLocation.latlng);
}
}
//----------------------------------------------------------------------------
function animate(d) {
if (d>eol) {
marker.setPosition(endLocation.latlng);
return;
}
var p = polyline.GetPointAtDistance(d);
//map.panTo(p);
marker.setPosition(p);
updatePoly(d);
timerHandle = setTimeout("animate("+(d+step)+")", tick);
}
//-------------------------------------------------------------------------
function startAnimation() {
eol=polyline.Distance();
map.setCenter(polyline.getPath().getAt(0));
poly2 = new google.maps.Polyline({path: [polyline.getPath().getAt(0)], strokeColor:"#FFFF00", strokeWeight:3});
setTimeout("animate(50)",2000); // Allow time for the initial map display
}
//----------------------------------------------------------------------------
</script>
</head>
<body onload="initialize()">
<div id="tools">
<button onclick="setRoutes();">Start</button>
</div>
<div id="map_canvas" style="width:100%;height:100%;"></div>
If you want to animate multiple markers you will have to change the animate and startAnimation functions to handle multiple markers (probably make all the variables into arrays).
code snippet:
var map; var directionDisplay; var directionsService; var stepDisplay; var position; var marker = []; var polyline = []; var poly2 = []; var poly = null; var startLocation = []; var endLocation = []; var timerHandle = []; var speed = 0.000005, wait = 1; var infowindow = null; var myPano; var panoClient; var nextPanoId; var startLoc = new Array(); startLoc[0] = 'rio claro, trinidad'; startLoc[1] = 'preysal, trinidad'; startLoc[2] = 'san fernando, trinidad'; startLoc[3] = 'couva, trinidad'; var endLoc = new Array(); endLoc[0] = 'princes town, trinidad'; endLoc[1] = 'tabaquite, trinidad'; endLoc[2] = 'mayaro, trinidad'; endLoc[3] = 'arima, trinidad'; var Colors = ["#FF0000", "#00FF00", "#0000FF"]; function initialize() { infowindow = new google.maps.InfoWindow( { size: new google.maps.Size(150,50) }); var myOptions = { zoom: 10, mapTypeId: google.maps.MapTypeId.ROADMAP } map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); address = 'Trinidad and Tobago' geocoder = new google.maps.Geocoder(); geocoder.geocode( { 'address': address}, function(results, status) { map.fitBounds(results[0].geometry.viewport); }); // setRoutes(); } function createMarker(latlng, label, html) { // alert("createMarker("+latlng+","+label+","+html+","+color+")"); var contentString = '<b>'+label+'</b><br>'+html; var marker = new google.maps.Marker({ position: latlng, map: map, title: label, zIndex: Math.round(latlng.lat()*-100000)<<5 }); marker.myname = label; google.maps.event.addListener(marker, 'click', function() { infowindow.setContent(contentString); infowindow.open(map,marker); }); return marker; } function setRoutes(){ var directionsDisplay = new Array(); for (var i=0; i< startLoc.length; i++){ var rendererOptions = { map: map, suppressMarkers : true, preserveViewport: true } directionsService = new google.maps.DirectionsService(); var travelMode = google.maps.DirectionsTravelMode.DRIVING; var request = { origin: startLoc[i], destination: endLoc[i], travelMode: travelMode }; directionsService.route(request,makeRouteCallback(i,directionsDisplay[i])); } function makeRouteCallback(routeNum,disp){ if (polyline[routeNum] && (polyline[routeNum].getMap() != null)) { startAnimation(routeNum); return; } return function(response, status){ if (status == google.maps.DirectionsStatus.OK){ var bounds = new google.maps.LatLngBounds(); var route = response.routes[0]; startLocation[routeNum] = new Object(); endLocation[routeNum] = new Object(); polyline[routeNum] = new google.maps.Polyline({ path: [], strokeColor: '#FFFF00', strokeWeight: 3 }); poly2[routeNum] = new google.maps.Polyline({ path: [], strokeColor: '#FFFF00', strokeWeight: 3 }); // For each route, display summary information. var path = response.routes[0].overview_path; var legs = response.routes[0].legs; disp = new google.maps.DirectionsRenderer(rendererOptions); disp.setMap(map); disp.setDirections(response); //Markers for (i=0;i<legs.length;i++) { if (i == 0) { startLocation[routeNum].latlng = legs[i].start_location; startLocation[routeNum].address = legs[i].start_address; // marker = google.maps.Marker({map:map,position: startLocation.latlng}); marker[routeNum] = createMarker(legs[i].start_location,"start",legs[i].start_address,"green"); } endLocation[routeNum].latlng = legs[i].end_location; endLocation[routeNum].address = legs[i].end_address; var steps = legs[i].steps; for (j=0;j<steps.length;j++) { var nextSegment = steps[j].path; var nextSegment = steps[j].path; for (k=0;k<nextSegment.length;k++) { polyline[routeNum].getPath().push(nextSegment[k]); //bounds.extend(nextSegment[k]); } } } } polyline[routeNum].setMap(map); //map.fitBounds(bounds); startAnimation(routeNum); } // else alert("Directions request failed: "+status); } } var lastVertex = 1; var stepnum=0; var step = 50; // 5; // metres var tick = 100; // milliseconds var eol= []; //---------------------------------------------------------------------- function updatePoly(i,d) { // Spawn a new polyline every 20 vertices, because updating a 100-vertex poly is too slow if (poly2[i].getPath().getLength() > 20) { poly2[i]=new google.maps.Polyline([polyline[i].getPath().getAt(lastVertex-1)]); // map.addOverlay(poly2) } if (polyline[i].GetIndexAtDistance(d) < lastVertex+2) { if (poly2[i].getPath().getLength()>1) { poly2[i].getPath().removeAt(poly2[i].getPath().getLength()-1) } poly2[i].getPath().insertAt(poly2[i].getPath().getLength(),polyline[i].GetPointAtDistance(d)); } else { poly2[i].getPath().insertAt(poly2[i].getPath().getLength(),endLocation[i].latlng); } } //---------------------------------------------------------------------------- function animate(index,d) { if (d>eol[index]) { marker[index].setPosition(endLocation[index].latlng); return; } var p = polyline[index].GetPointAtDistance(d); //map.panTo(p); marker[index].setPosition(p); updatePoly(index,d); timerHandle[index] = setTimeout("animate("+index+","+(d+step)+")", tick); } //------------------------------------------------------------------------- function startAnimation(index) { if (timerHandle[index]) clearTimeout(timerHandle[index]); eol[index]=polyline[index].Distance(); map.setCenter(polyline[index].getPath().getAt(0)); poly2[index] = new google.maps.Polyline({path: [polyline[index].getPath().getAt(0)], strokeColor:"#FFFF00", strokeWeight:3}); timerHandle[index] = setTimeout("animate("+index+",50)",2000); // Allow time for the initial map display } //---------------------------------------------------------------------------- google.maps.event.addDomListener(window,'load',initialize); //src="http://www.geocodezip.com/scripts/v3_epoly.js" /*********************************************************************\\ * * * epolys.js by Mike Williams * * updated to API v3 by Larry Ross * * * * A Google Maps API Extension * * * * Adds various Methods to google.maps.Polygon and google.maps.Polyline * * .Distance() returns the length of the poly path * * * * .GetPointAtDistance() returns a GLatLng at the specified distance * * along the path. * * The distance is specified in metres * * Reurns null if the path is shorter than that * * * * .GetPointsAtDistance() returns an array of GLatLngs at the * * specified interval along the path. * * The distance is specified in metres * * * \\*********************************************************************/ // === first support methods that don't (yet) exist in v3 google.maps.LatLng.prototype.distanceFrom = function(newLatLng) { var EarthRadiusMeters = 6378137.0; // meters var lat1 = this.lat(); var lon1 = this.lng(); var lat2 = newLatLng.lat(); var lon2 = newLatLng.lng(); var dLat = (lat2-lat1) * Math.PI / 180; var dLon = (lon2-lon1) * Math.PI / 180; var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1 * Math.PI / 180 ) * Math.cos(lat2 * Math.PI / 180 ) * Math.sin(dLon/2) * Math.sin(dLon/2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var d = EarthRadiusMeters * c; return d; } google.maps.LatLng.prototype.latRadians = function() { return this.lat() * Math.PI/180; } google.maps.LatLng.prototype.lngRadians = function() { return this.lng() * Math.PI/180; } // === A method which returns the length of a path in metres === google.maps.Polyline.prototype.Distance = function() { var dist = 0; for (var i=1; i < this.getPath().getLength(); i++) { dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i-1)); } return dist; } // === A method which returns a GLatLng of a point a given distance along the path === // === Returns null if the path is shorter than the specified distance === google.maps.Polyline.prototype.GetPointAtDistance = function(metres) { // some awkward special cases if (metres == 0) return this.getPath().getAt(0); if (metres < 0) return null; if (this.getPath().getLength() < 2) return null; var dist=0; var olddist=0; for (var i=1; (i < this.getPath().getLength() && dist < metres); i++) { olddist = dist; dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i-1)); } if (dist < metres) { return null; } var p1= this.getPath().getAt(i-2); var p2= this.getPath().getAt(i-1); var m = (metres-olddist)/(dist-olddist); return new google.maps.LatLng( p1.lat() + (p2.lat()-p1.lat())*m, p1.lng() + (p2.lng()-p1.lng())*m); } // === A method which returns an array of GLatLngs of points a given interval along the path === google.maps.Polyline.prototype.GetPointsAtDistance = function(metres) { var next = metres; var points = []; // some awkward special cases if (metres <= 0) return points; var dist=0; var olddist=0; for (var i=1; (i < this.getPath().getLength()); i++) { olddist = dist; dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i-1)); while (dist > next) { var p1= this.getPath().getAt(i-1); var p2= this.getPath().getAt(i); var m = (next-olddist)/(dist-olddist); points.push(new google.maps.LatLng( p1.lat() + (p2.lat()-p1.lat())*m, p1.lng() + (p2.lng()-p1.lng())*m)); next += metres; } } return points; } // === A method which returns the Vertex number at a given distance along the path === // === Returns null if the path is shorter than the specified distance === google.maps.Polyline.prototype.GetIndexAtDistance = function(metres) { // some awkward special cases if (metres == 0) return this.getPath().getAt(0); if (metres < 0) return null; var dist=0; var olddist=0; for (var i=1; (i < this.getPath().getLength() && dist < metres); i++) { olddist = dist; dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i-1)); } if (dist < metres) {return null;} return i; }
html{height:100%;} body{height:100%;margin:0px;font-family: Helvetica,Arial;}
<script type="text/javascript" src="https://maps.google.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script> <div id="tools"> <button onclick="setRoutes();">Start</button> </div> <div id="map_canvas" style="width:100%;height:100%;"></div>
You're using a lot of variables that aren't declared with var
inside for()
loops. Most notably the for (i=...
in makeRouteCallback(disp)
when there's already a variable i
in setRoutes()
. I think this might be causing this behavior.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.