animating a map marker using request animation frame in google maps api v3

流过昼夜 提交于 2020-02-23 07:37:29

问题


I've managed to animate a google map marker around a route in google maps api v3 using setTimeout, but I'd like to find a way to do it using request animation frame. However, when I try to do this - the marker just seems to jump from beginning of the path to the end, with no animation. Any ideas where I'm going astray? Here's the relevant parts of my code using setTimeout, but you can also download / view the files in github:

self.animateRun = function(curDist){ //moves the runner
  if (curDist > runnerAnimationConfig.dist) { //if we've passed the end point, exit this loop and focus on the endpoint

    var endLatLng = getLatLng(raceMarkers.endPoint.lat,raceMarkers.endPoint.lng);

    self.map.panTo(endLatLng);
    runnerMarker.setPosition();
    return;
  }

  var curPoint = racePath.GetPointAtDistance(curDist); 
  self.map.panTo(curPoint);
  runnerMarker.setPosition(curPoint);
  var newDist = curDist + runnerAnimationConfig.step;
  //requestAnimationFrame(self.animateRun(newDist));
  timerHandle = setTimeout("MAP.animateRun("+(curDist+runnerAnimationConfig.step)+")", runnerAnimationConfig.tick);

}

And what I tried to do with request animation frame was to place this code from creativeJS:

// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating

// requestAnimationFrame polyfill by Erik Möller
// fixes from Paul Irish and Tino Zijdel

(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

commenting out the setTimeout and uncommenting the requestanimationframe line. But this didn't work.

I wondered if maybe you couldn't pass parameters, so I changed the function animateRun to accept no parameters, and instead reference a global variable, curDist, but this still didn't work. I'm not sure what else to try or what might be going wrong. I can trace out the call in requestanimationframe and it works - i've even input a sort of modulus as a timer to try and slow it down (var frameCount = 0, frameCount increases once each call to animateRun. If framecount%100 = 0, do all the stuff in animateRun) but that didn't work either. That function looked something like this:

var curDist = 0;
var curFrame = 0;
runnerAnimationConfig.step = 5;

    self.animateRun = function(){ //moves the runner



            if (curDist > runnerAnimationConfig.dist) { //if we've passed the end point, exit this loop and focus on the endpoint

              var endLatLng = getLatLng(raceMarkers.endPoint.lat,raceMarkers.endPoint.lng);

              self.map.panTo(endLatLng);
              runnerMarker.setPosition();
              return;
            }

            if (curFrame%100 === 0){

            var curPoint = racePath.GetPointAtDistance(curDist); 
            self.map.panTo(curPoint);
            runnerMarker.setPosition(curPoint);

            }

            curFrame += 1;
            curDist = curDist + runnerAnimationConfig.step;

            requestAnimationFrame(self.animateRun);


          }

Thanks if you've got any ideas on how to solve this.


回答1:


When you do:

requestAnimationFrame(self.animateRun);

You are only passing the value of the self.animateRun function definition to requestAnimationFrame, when what you really need to do is pass a reference to the particular instance of MapClass's animateRun method in a manner which maintains a reference to the current 'this' object (self).

Then, in your startRunnerAnimation function, it would be a cleaner solution to watch for the map objects tilesloaded event rather than the setTimeout

That function looked something like this:

Change that, as well as your startRunnerAnimation() function to the following:

self.curDist = 0;

self.animateRun = function(){ //moves the runner
        if (self.curDist > runnerAnimationConfig.dist) { //if we've passed the end point, exit this loop and focus on the endpoint
          var endLatLng = getLatLng(raceMarkers.endPoint.lat,raceMarkers.endPoint.lng);
          self.map.panTo(endLatLng);
          runnerMarker.setPosition();
          return;
        }
        var curPoint = racePath.GetPointAtDistance(self.curDist); 
        self.map.panTo(curPoint);
        runnerMarker.setPosition(curPoint);
        self.curDist += runnerAnimationConfig.step;
        window.requestAnimationFrame(function () {self.animateRun();});
};

function startRunnerAnimation(){
    runnerAnimationConfig.dist = racePath.Distance();
    self.map.setCenter(racePath.getPath().getAt(0));
    var lstnr = google.maps.event.addListener(self.map, 'tilesloaded', function () {
         //only want this happening on initial load, not every time the tiles change
        google.maps.event.removeListener(lstnr);
        window.requestAnimationFrame(function () {self.animateRun();});
    });
}


来源:https://stackoverflow.com/questions/18033123/animating-a-map-marker-using-request-animation-frame-in-google-maps-api-v3

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