Angular Directive Number Effects

Angularjs Directive for Number Counting Effects

Hi guys, I was working on a simple dashboard which shows a number of views and likes. Instead of showing static numbers, I decided to give some number changing effects. I wanted an animation where number would count up and slow down at the end. Before I write my own angular directive, I decided to check online if someone from angular community already have something like it. After googling for few minutes, I couldn’t find exactly what I was looking for but I did find an angular directive count-to which was close to what I wanted. I took his work and modified it for my needs. Below is my hack.

Angular Directive Number Effects

Angular Directive Number Effects

  .directive('animateNumbers',function ($timeout) {
        return {
            replace: false,
            scope: true,
            link: function (scope, element, attrs) {
                var e = element[0];
                var refreshInterval = 30;
                var duration = 1000; //milliseconds
				var number = parseInt(e.innerText);
                var step = 0;
                var num = 0;
                var steps = Math.ceil(duration / refreshInterval);
                var increment = (number / steps);
                var percentCompleted = 0;
                var lastNumberSlowCount = 3;
                if(number > lastNumberSlowCount){
					number = number - lastNumberSlowCount;
                }
				scope.timoutId = null;
                var counter = function () {
                    scope.timoutId = $timeout(function () {
                        num += increment;
                        percentCompleted = Math.round((num/number) * 100);
                        if(percentCompleted > 60 && percentCompleted < 80){
                        	refreshInterval = refreshInterval + 10;
                        }
                        else if (percentCompleted > 90){
                        	refreshInterval = 200;
                        }
                        step++;
                        if (step >= steps) {
                            $timeout.cancel(scope.timoutId);
                            num = number;
                            e.textContent = number;
                            if(number > lastNumberSlowCount){
								slowCounter();
                            }
                        } else {
                            e.textContent = Math.round(num);
                            counter();
                        }
                    }, refreshInterval);
                }
                var slowCounter = function(){
					scope.timoutId = $timeout(function () {
						lastNumberSlowCount --;
						if(lastNumberSlowCount  < 0){
							$timeout.cancel(scope.timoutId);
						}
						else {
							number++;
							e.textContent = number;
							slowCounter();
						}
					},500)
                }
				counter();
                return true;
            }
        }
    });

Finally, just throw in animate-numbers attribute in your tag like <div animate-numbers>1021</div> and you are good to go.


Momin