需要将$ timeout和$ apply与requestAnimationFrame一起使用

Lie*_*iem 2 timeout requestanimationframe angularjs angularjs-digest

我正在尝试使用requestAnimationFrame创建具有滚动编号的javascript动画

In order to see the see the animation rolling, I need to use a $apply to refresh the view. The problem here is when I start the animation, the digest cycle is already running so my $apply return an error "$apply already in progress".

Looking for a solution I use $timeout of 0 which work perfectly but I was wondering if there was other solution to avoid using a timeout that is not really good in terms of performance?

Thanks for your help!

Html Code:

<div ng-app="myApp">
  <div ng-controller="myController as ctrl">
    <animated-counter data-from='0' data-to='{{ctrl.limit}}'></animated-counter>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

Javascript Code:

(function(){
'use strict';

angular
    .module('myApp', [])
    .directive('animatedCounter', AnimatedCounter);

    AnimatedCounter.$inject = ['$timeout'];

    function AnimatedCounter($timeout) {
        return {
            restrict: 'E',
            template: '<div>{{num}}%</div>',
            link: function (scope, element, attrs) {
                scope.num = parseInt(attrs.from);
                var max = parseInt(attrs.to);

                //Loop to increment the num
                function animloop() {
                    if (scope.num >= max) { //Stop recursive when max reach
                        return;
                    }
                    requestAnimationFrame(animloop);
                    scope.$apply(function() {
                        scope.num += 1;
                    });
                }

                // $timeout(function() { //if I use $timeout it works perfectly
                    animloop();
                // });
            }
        };
    }


 angular
    .module('myApp')
    .controller('myController', myController);

    function myController() {
       var vm = this;
       vm.limit = 100;
    }
})();
Run Code Online (Sandbox Code Playgroud)

You can find here a CodePen

http://codepen.io/phliem/pen/ZWOjwz?editors=1011

Lie*_*iem 5

如果我像HadiJZ所说的那样使用$ evalAsync(),那么效果很好!

只需要更换

scope.$apply(function() {
   scope.num += 1;
});
Run Code Online (Sandbox Code Playgroud)

通过

scope.$evalAsync(function() {
   scope.num += 1;
})
Run Code Online (Sandbox Code Playgroud)

这里有一篇很好的文章http://www.bennadel.com/blog/2605-scope-evalasync-vs-timeout-in-angularjs.htm