How to animate a custom Google Maps marker along a route?

自作多情 提交于 2019-11-27 17:24:44

A pretty cool example is here:

http://www.kmcgraphics.com/google/

Unfortunately, there is no automatic-marker-movement function in the official GMaps collection.

However, if you have a GRoute, that would mean you have a set of points. To loop through the route steps, you could use something like this:

for (var c = 0; c < yourroute.getNumSteps(); c++) { 
    yourmarker.setLatLng(yourroute.getStep(c).getLatLng());
}

Of course, you'll probably want to do this asynchronously using the timers:

function moveToStep(yourmarker,yourroute,c) {
    if {yourroute.getNumSteps() > c) {
        yourmarker.setLatLng(yourroute.getStep(c).getLatLng());
        window.setTimeout(function(){
            moveToStep(yourmarker,yourroute,c+1);
        },500);
    }
}

moveToStep(marker,route,0);

For even smoother movement, you could interpolate the points from those you already have.

Here is my solution that works with the v3 API. This animates the marker not with a fixed velocity, but based on the calculated route duration. There is a speed factor, so for example you can drive through the route 10x faster than in reality.

I've tried to do it as simple as possible. Feel free to use it.

var autoDriveSteps = new Array();
var speedFactor = 10; // 10x faster animated drive

function setAnimatedRoute(origin, destination, map) {
    // init routing services
    var directionsService = new google.maps.DirectionsService;
    var directionsRenderer = new google.maps.DirectionsRenderer({
        map: map
    });

    //calculate route
    directionsService.route({
            origin: origin,
            destination: destination,
            travelMode: google.maps.TravelMode.DRIVING
        },
        function(response, status) {
            if (status == google.maps.DirectionsStatus.OK) {
                // display the route
                directionsRenderer.setDirections(response);

                // calculate positions for the animation steps
                // the result is an array of LatLng, stored in autoDriveSteps
                autoDriveSteps = new Array();
                var remainingSeconds = 0;
                var leg = response.routes[0].legs[0]; // supporting single route, single legs currently
                leg.steps.forEach(function(step) {
                    var stepSeconds = step.duration.value;
                    var nextStopSeconds = speedFactor - remainingSeconds;
                    while (nextStopSeconds <= stepSeconds) {
                        var nextStopLatLng = getPointBetween(step.start_location, step.end_location, nextStopSeconds / stepSeconds);
                        autoDriveSteps.push(nextStopLatLng);
                        nextStopSeconds += speedFactor;
                    }
                    remainingSeconds = stepSeconds + speedFactor - nextStopSeconds;
                });
                if (remainingSeconds > 0) {
                    autoDriveSteps.push(leg.end_location);
                }
            } else {
                window.alert('Directions request failed due to ' + status);
            }
        });
}

// helper method to calculate a point between A and B at some ratio
function getPointBetween(a, b, ratio) {
    return new google.maps.LatLng(a.lat() + (b.lat() - a.lat()) * ratio, a.lng() + (b.lng() - a.lng()) * ratio);
}

// start the route simulation   
function startRouteAnimation(marker) {
    var autoDriveTimer = setInterval(function () {
            // stop the timer if the route is finished
            if (autoDriveSteps.length === 0) {
                clearInterval(autoDriveTimer);
            } else {
                // move marker to the next position (always the first in the array)
                marker.setPosition(autoDriveSteps[0]);
                // remove the processed position
                autoDriveSteps.shift();
            }
        },
        1000);
}

Usage:

setAnimatedRoute("source address or LatLng ...", "destination address or LatLng ...", map);
// start simulation on button click...
$("#simulateRouteButton").click(function() {
    startRouteAnimation(agentMarker);
});

Hope this will help you here is a button and when you click on them marker move from source to destination route. setRoutes method is use for set the route of 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]));

    } 

Make route after setting them.

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

  }

}

At last we call start animation function

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
}

You can be found full code on GeekOnJava blog and copy that code and run them and output on youtube.

It doesn't move something automatically, but you should check out the Google Drive experiment by phatfusion. Looking at the code might help you out.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!