0

我已经设法使用 setTimeout 在 google maps api v3 中的路线周围为 google map 标记设置动画,但我想找到一种使用请求动画帧的方法。但是,当我尝试这样做时 - 标记似乎只是从路径的开头跳到了结尾,没有动画。有什么想法我会误入歧途吗?这是我使用 setTimeout 的代码的相关部分,但您也可以在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);

}

我试图用请求动画帧做的是从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);
        };
}());

注释掉 setTimeout 并取消注释 requestanimationframe 行。但这没有用。

我想知道您是否无法传递参数,所以我将函数 animateRun 更改为不接受任何参数,而是引用一个全局变量 curDist,但这仍然不起作用。我不确定还有什么可以尝试或可能出了什么问题。我可以在 requestanimationframe 中追踪调用并且它有效 - 我什至输入了一种模数作为计时器来尝试减慢它(var frameCount = 0,frameCount 在每次调用 animateRun 时增加一次。如果 framecount%100 = 0 ,在 animateRun 中做所有的事情),但这也不起作用。该函数看起来像这样:

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


          }

感谢您对如何解决此问题有任何想法。

4

1 回答 1

0

当你这样做时:

requestAnimationFrame(self.animateRun);

您只是将 self.animateRun 函数定义的值传递给 requestAnimationFrame,而您真正需要做的是以保持对当前“this”对象的引用的方式传递对 MapClass 的 animateRun 方法的特定实例的引用(自己)。

然后,在您的 startRunnerAnimation 函数中,监视地图对象的 tilesloaded 事件而不是 setTimeout 将是一个更简洁的解决方案

该函数看起来像这样:

将它以及您的 startRunnerAnimation() 函数更改为以下内容:

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();});
    });
}
于 2013-08-04T05:55:45.833 回答