使用JS播放一系列图像,使用$ timeout来安排帧

时间:2016-01-26 17:20:20

标签: javascript angularjs

我使用AngularJS预取缓存客户端中的图像,然后我想为这些预取图像设置动画。

我的预取代码:

$scope.prefetch=function(limit) {
  for (var i=0; i<limit; i++) {
    var date = new Date($scope.dt);
    if ($scope.fileFlag == false) {
      if ($scope.viewmodel.timeResolution == 'yearly')
        date = new Date(date.setFullYear(date.getFullYear() + i));
      else if ($scope.viewmodel.timeResolution == 'monthly')
        date = new Date(date.setMonth(date.getMonth() + i));
      else if ($scope.viewmodel.timeResolution == 'daily') {
        date = new Date(date.setDate(date.getDate() + i));
      }
    } else {
      date = $scope.files[$scope.files.indexOf($scope.idSelectedVote) + i];
    }

    console.log( $http.get(site_url + "mwf/" + $scope.viewmodel.dataSet + "/" + $scope.viewmodel.varName + "/" + $scope.viewmodel.region + "/" + date + "/map/?vMin=" + $scope.VMin + "&vMax=" + $scope.VMax + "&type=" + $scope.viewmodel.type + "&cmap=" + $scope.viewmodel.colorMap, {'cache': true}));
  }
};

然后我做这样的事情来播放这些图像

$scope.play=function(limit) {
  for (var i=0; i<limit; i++) {
    $scope.map.src= site_url + "mwf/" + $scope.viewmodel.dataSet + "/" + $scope.viewmodel.varName + "/" +  $scope.viewmodel.region + "/" +  parseInt(date)+i + "/map/?vMin=" + $scope.VMin + "&vMax=" + $scope.VMax + "&type=" + $scope.viewmodel.type + "&cmap=" + $scope.viewmodel.colorMap;
    $scope.sleepFor(500);
  }                
};

$scope.sleepFor = function( sleepDuration ) {
  var now = new Date().getTime();
  while(new Date().getTime() < now + sleepDuration){ /* do nothing */ }
}

我的问题是当我拨打play(4)时,它只显示第一张和最后一张图片,而不是动画。有关如何改进此代码或不同方法的任何想法,以便我可以做到这一点?

2 个答案:

答案 0 :(得分:4)

你的sleepFor是一个空闲的循环:你旋转并且什么也不做,但你阻止任何其他的工作完成。这不是Javascript在一段时间内延迟工作的方式,也不是安排函数在以后运行的方式。在Javascript中我们使用window.setTimeout - 在Angular中,我们提供了方便的$timeout服务来提供:

$scope.play = function(limit) {
  for (var i=0; i < limit; i++) {
    $scope.map.src = site_url + "mwf/" + $scope.viewmodel.dataSet + "/" + $scope.viewmodel.varName + "/" +  $scope.viewmodel.region + "/" +  parseInt(date)+i + "/map/?vMin=" + $scope.VMin + "&vMax=" + $scope.VMax + "&type=" + $scope.viewmodel.type + "&cmap=" + $scope.viewmodel.colorMap;

    var nextFrameMs = 500;
    $timeout($scope.play, nextFrameMs);
  }
};

在您的示例中,只要向您提供$scope - 假设这是在控制器中,您将有一些像module.controller($scope, ...)这样的行 - 您必须注入$timeout服务能够使用它。

其他资源:

答案 1 :(得分:2)

您必须使用间隔,否则您的代码将阻止执行其他代码

使用Angular的内置$interval服务是解决方案:

var playInterval;
$scope.play = function(limit) {
    var interval = 1000 / 20; //20 frames per second
    var i = 0;
    $interval.cancel(playInterval); //stop previous animations if any
    if(i < limit) {
        $scope.map.src = getSrc(i++);                   
        var cache = $interval(function() {
            if(i >= limit) {                                        
                return $interval.cancel(playInterval); //or you can replace with `i = 0;` to loop the animation
            }
            $scope.map.src = getSrc(i++);
        }, interval);
    }
};

function getSrc(i) {
    return site_url + "mwf/" + $scope.viewmodel.dataSet + "/" + $scope.viewmodel.varName + "/" +  $scope.viewmodel.region + "/" +  parseInt(date)+i + "/map/?vMin=" + $scope.VMin + "&vMax=" + $scope.VMax + "&type=" + $scope.viewmodel.type + "&cmap=" + $scope.viewmodel.colorMap;
}