简体   繁体   中英

Animating Multiple Markers

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).

example

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM