Animating Multiple Markers

前端 未结 2 1829
执念已碎
执念已碎 2020-12-01 20:32

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.

相关标签:
2条回答
  • 2020-12-01 21:00

    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>

    0 讨论(0)
  • 2020-12-01 21:04

    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.

    0 讨论(0)
提交回复
热议问题