【问题标题】:Animating Multiple Markers动画多个标记
【发布时间】:2013-08-17 05:15:24
【问题描述】:

我在地图上有几个标记,并绘制了折线。我想沿着折线的路径移动每个标记,以模拟每个标记的同时移动。

我在执行此操作时遇到问题,我只能移动最后一个标记,其余的则没有。作为使用这种编程技术的新手,我认为我的代码有问题,尤其是我尝试为每个标记设置动画的方式。我需要一些指导。

这是我迄今为止的工作: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>

【问题讨论】:

    标签: javascript jquery google-maps google-maps-api-3 google-maps-markers


    【解决方案1】:

    您在for() 循环中使用了很多未使用var 声明的变量。最值得注意的是makeRouteCallback(disp) 中的for (i=...,此时setRoutes() 中已经存在变量i。我认为这可能会导致这种行为。

    【讨论】:

      【解决方案2】:

      如果您想为多个标记设置动画,则必须更改 animate 和 startAnimation 函数以处理多个标记(可能将所有变量放入数组中)。

      example

      代码sn-p:

      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>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-11
        • 2019-06-28
        • 2018-02-03
        相关资源
        最近更新 更多