diff options
| author | Matias Niemelä | 2014-02-24 19:43:57 -0500 |
|---|---|---|
| committer | Matias Niemelä | 2014-02-24 21:23:18 -0500 |
| commit | 4c4537e65e6cf911c9659b562d89e3330ce3ffae (patch) | |
| tree | 3f9e6736a314073b5516beab3c86d7709e887b6b /src | |
| parent | 62761428eff3a53e69367449eb81869e59e75e39 (diff) | |
| download | angular.js-4c4537e65e6cf911c9659b562d89e3330ce3ffae.tar.bz2 | |
perf($animate): use rAF instead of timeouts to issue animation callbacks
Diffstat (limited to 'src')
| -rw-r--r-- | src/ng/animate.js | 16 | ||||
| -rw-r--r-- | src/ngAnimate/animate.js | 54 | ||||
| -rw-r--r-- | src/ngMock/angular-mocks.js | 15 |
3 files changed, 37 insertions, 48 deletions
diff --git a/src/ng/animate.js b/src/ng/animate.js index 130e61e7..d90f086b 100644 --- a/src/ng/animate.js +++ b/src/ng/animate.js @@ -81,7 +81,11 @@ var $AnimateProvider = ['$provide', function($provide) { return this.$$classNameFilter; }; - this.$get = ['$timeout', function($timeout) { + this.$get = ['$timeout', '$$asyncCallback', function($timeout, $$asyncCallback) { + + function async(fn) { + fn && $$asyncCallback(fn); + } /** * @@ -126,7 +130,7 @@ var $AnimateProvider = ['$provide', function($provide) { } parent.append(element); } - done && $timeout(done, 0, false); + async(done); }, /** @@ -142,7 +146,7 @@ var $AnimateProvider = ['$provide', function($provide) { */ leave : function(element, done) { element.remove(); - done && $timeout(done, 0, false); + async(done); }, /** @@ -189,7 +193,7 @@ var $AnimateProvider = ['$provide', function($provide) { forEach(element, function (element) { jqLiteAddClass(element, className); }); - done && $timeout(done, 0, false); + async(done); }, /** @@ -212,7 +216,7 @@ var $AnimateProvider = ['$provide', function($provide) { forEach(element, function (element) { jqLiteRemoveClass(element, className); }); - done && $timeout(done, 0, false); + async(done); }, /** @@ -234,7 +238,7 @@ var $AnimateProvider = ['$provide', function($provide) { jqLiteAddClass(element, add); jqLiteRemoveClass(element, remove); }); - done && $timeout(done, 0, false); + async(done); }, enabled : noop diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js index 5c0ed917..6ccf6a5d 100644 --- a/src/ngAnimate/animate.js +++ b/src/ngAnimate/animate.js @@ -247,42 +247,24 @@ angular.module('ngAnimate', ['ng']) * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application. * */ - .factory('$$animateReflow', ['$window', '$timeout', '$document', - function($window, $timeout, $document) { + + //this private service is only used within CSS-enabled animations + //IE8 + IE9 do not support rAF natively, but that is fine since they + //also don't support transitions and keyframes which means that the code + //below will never be used by the two browsers. + .factory('$$animateReflow', ['$$rAF', '$document', function($$rAF, $document) { var bod = $document[0].body; - var requestAnimationFrame = $window.requestAnimationFrame || - $window.webkitRequestAnimationFrame || - function(fn) { - return $timeout(fn, 10, false); - }; - - var cancelAnimationFrame = $window.cancelAnimationFrame || - $window.webkitCancelAnimationFrame || - function(timer) { - return $timeout.cancel(timer); - }; return function(fn) { - var id = requestAnimationFrame(function() { + //the returned function acts as the cancellation function + return $$rAF(function() { + //the line below will force the browser to perform a repaint + //so that all the animated elements within the animation frame + //will be properly updated and drawn on screen. This is + //required to perform multi-class CSS based animations with + //Firefox. DO NOT REMOVE THIS LINE. var a = bod.offsetWidth + 1; fn(); }); - return function() { - cancelAnimationFrame(id); - }; - }; - }]) - - .factory('$$asyncQueueBuffer', ['$timeout', function($timeout) { - var timer, queue = []; - return function(fn) { - $timeout.cancel(timer); - queue.push(fn); - timer = $timeout(function() { - for(var i = 0; i < queue.length; i++) { - queue[i](); - } - queue = []; - }, 0, false); }; }]) @@ -313,8 +295,8 @@ angular.module('ngAnimate', ['ng']) return extractElementNode(elm1) == extractElementNode(elm2); } - $provide.decorator('$animate', ['$delegate', '$injector', '$sniffer', '$rootElement', '$$asyncQueueBuffer', '$rootScope', '$document', - function($delegate, $injector, $sniffer, $rootElement, $$asyncQueueBuffer, $rootScope, $document) { + $provide.decorator('$animate', ['$delegate', '$injector', '$sniffer', '$rootElement', '$$asyncCallback', '$rootScope', '$document', + function($delegate, $injector, $sniffer, $rootElement, $$asyncCallback, $rootScope, $document) { var globalAnimationCounter = 0; $rootElement.data(NG_ANIMATE_STATE, rootAnimateState); @@ -876,7 +858,7 @@ angular.module('ngAnimate', ['ng']) function fireDOMCallback(animationPhase) { var eventName = '$animate:' + animationPhase; if(elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) { - $$asyncQueueBuffer(function() { + $$asyncCallback(function() { element.triggerHandler(eventName, { event : animationEvent, className : className @@ -896,7 +878,7 @@ angular.module('ngAnimate', ['ng']) function fireDoneCallbackAsync() { fireDOMCallback('close'); if(doneCallback) { - $$asyncQueueBuffer(function() { + $$asyncCallback(function() { doneCallback(); }); } @@ -923,7 +905,7 @@ angular.module('ngAnimate', ['ng']) if(isClassBased) { cleanup(element, className); } else { - $$asyncQueueBuffer(function() { + $$asyncCallback(function() { var data = element.data(NG_ANIMATE_STATE) || {}; if(localAnimationCount == data.index) { cleanup(element, className, animationEvent); diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index bcd6cc1f..c9f31431 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -757,21 +757,24 @@ angular.mock.TzDate.prototype = Date.prototype; angular.mock.animate = angular.module('ngAnimateMock', ['ng']) .config(['$provide', function($provide) { - var reflowQueue = []; + var reflowQueue = []; $provide.value('$$animateReflow', function(fn) { + var index = reflowQueue.length; reflowQueue.push(fn); - return angular.noop; + return function cancel() { + reflowQueue.splice(index, 1); + }; }); - $provide.decorator('$animate', function($delegate) { + $provide.decorator('$animate', function($delegate, $$asyncCallback) { var animate = { queue : [], enabled : $delegate.enabled, + triggerCallbacks : function() { + $$asyncCallback.flush(); + }, triggerReflow : function() { - if(reflowQueue.length === 0) { - throw new Error('No animation reflows present'); - } angular.forEach(reflowQueue, function(fn) { fn(); }); |
