Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 4ae3184

Browse files
committed
feat($animate): use requestAnimationFrame instead of a timeout to issue a reflow
Closes #4278 Closes #4225
1 parent ed53100 commit 4ae3184

File tree

4 files changed

+142
-82
lines changed

4 files changed

+142
-82
lines changed

karma-docs.conf.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ module.exports = function(config) {
1010

1111
'build/angular.js',
1212
'build/angular-cookies.js',
13-
'build/angular-mocks.js',
1413
'build/angular-resource.js',
1514
'build/angular-touch.js',
1615
'build/angular-sanitize.js',
1716
'build/angular-route.js',
1817
'build/angular-animate.js',
18+
'build/angular-mocks.js',
1919

2020
'build/docs/components/lunr.js',
2121
'build/docs/components/google-code-prettify.js',

src/ngAnimate/animate.js

+31-6
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,28 @@ angular.module('ngAnimate', ['ng'])
248248
* Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.
249249
*
250250
*/
251+
.factory('$$animateReflow', ['$window', '$timeout', function($window, $timeout) {
252+
var requestAnimationFrame = $window.requestAnimationFrame ||
253+
$window.mozRequestAnimationFrame ||
254+
$window.webkitRequestAnimationFrame ||
255+
function(fn) {
256+
return $timeout(fn, 10, false);
257+
};
258+
259+
var cancelAnimationFrame = $window.cancelAnimationFrame ||
260+
$window.mozCancelAnimationFrame ||
261+
$window.webkitCancelAnimationFrame ||
262+
function(timer) {
263+
return $timeout.cancel(timer);
264+
};
265+
return function(fn) {
266+
var id = requestAnimationFrame(fn);
267+
return function() {
268+
cancelAnimationFrame(id);
269+
};
270+
};
271+
}])
272+
251273
.config(['$provide', '$animateProvider', function($provide, $animateProvider) {
252274
var noop = angular.noop;
253275
var forEach = angular.forEach;
@@ -872,7 +894,8 @@ angular.module('ngAnimate', ['ng'])
872894
}
873895
}]);
874896

875-
$animateProvider.register('', ['$window', '$sniffer', '$timeout', function($window, $sniffer, $timeout) {
897+
$animateProvider.register('', ['$window', '$sniffer', '$timeout', '$$animateReflow',
898+
function($window, $sniffer, $timeout, $$animateReflow) {
876899
// Detect proper transitionend/animationend event names.
877900
var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT;
878901

@@ -917,11 +940,13 @@ angular.module('ngAnimate', ['ng'])
917940
var parentCounter = 0;
918941
var animationReflowQueue = [];
919942
var animationElementQueue = [];
920-
var animationTimer;
943+
var cancelAnimationReflow;
921944
var closingAnimationTime = 0;
922945
var timeOut = false;
923946
function afterReflow(element, callback) {
924-
$timeout.cancel(animationTimer);
947+
if(cancelAnimationReflow) {
948+
cancelAnimationReflow();
949+
}
925950

926951
animationReflowQueue.push(callback);
927952

@@ -942,7 +967,7 @@ angular.module('ngAnimate', ['ng'])
942967
//a follow-up animation is midway in its animation
943968
elementData.animationCount = animationCounter;
944969

945-
animationTimer = $timeout(function() {
970+
cancelAnimationReflow = $$animateReflow(function() {
946971
forEach(animationReflowQueue, function(fn) {
947972
fn();
948973
});
@@ -963,11 +988,11 @@ angular.module('ngAnimate', ['ng'])
963988

964989
animationReflowQueue = [];
965990
animationElementQueue = [];
966-
animationTimer = null;
991+
cancelAnimationReflow = null;
967992
lookupCache = {};
968993
closingAnimationTime = 0;
969994
animationCounter++;
970-
}, 10, false);
995+
});
971996
}
972997

973998
function closeAllAnimations(elements, count) {

src/ngMock/angular-mocks.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,26 @@ angular.mock.TzDate = function (offset, timestamp) {
756756
angular.mock.TzDate.prototype = Date.prototype;
757757
/* jshint +W101 */
758758

759+
angular.module('ngAnimate').config(['$provide', function($provide) {
760+
var reflowQueue = [];
761+
$provide.value('$$animateReflow', function(fn) {
762+
reflowQueue.push(fn);
763+
return angular.noop;
764+
});
765+
$provide.decorator('$animate', function($delegate) {
766+
$delegate.triggerReflow = function() {
767+
if(reflowQueue.length === 0) {
768+
throw new Error('No animation reflows present');
769+
}
770+
angular.forEach(reflowQueue, function(fn) {
771+
fn();
772+
});
773+
reflowQueue = [];
774+
};
775+
return $delegate;
776+
});
777+
}]);
778+
759779
angular.mock.animate = angular.module('mock.animate', ['ng'])
760780

761781
.config(['$provide', function($provide) {
@@ -1913,7 +1933,6 @@ angular.mock.clearDataCache = function() {
19131933
};
19141934

19151935

1916-
19171936
if(window.jasmine || window.mocha) {
19181937

19191938
var currentSpec = null,

0 commit comments

Comments
 (0)