Skip to content

Commit

Permalink
feat($animate): use requestAnimationFrame instead of a timeout to iss…
Browse files Browse the repository at this point in the history
…ue a reflow

Closes angular#4278
Closes angular#4225
  • Loading branch information
matsko committed Jan 14, 2014
1 parent 72d86eb commit 17b4b39
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 82 deletions.
2 changes: 1 addition & 1 deletion karma-docs.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ module.exports = function(config) {

'build/angular.js',
'build/angular-cookies.js',
'build/angular-mocks.js',
'build/angular-resource.js',
'build/angular-touch.js',
'build/angular-sanitize.js',
'build/angular-route.js',
'build/angular-animate.js',
'build/angular-mocks.js',

'build/docs/components/lunr.js',
'build/docs/components/google-code-prettify.js',
Expand Down
37 changes: 31 additions & 6 deletions src/ngAnimate/animate.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,28 @@ 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', function($window, $timeout) {
var requestAnimationFrame = $window.requestAnimationFrame ||
$window.mozRequestAnimationFrame ||
$window.webkitRequestAnimationFrame ||
function(fn) {
return $timeout(fn, 10, false);
};

var cancelAnimationFrame = $window.cancelAnimationFrame ||
$window.mozCancelAnimationFrame ||
$window.webkitCancelAnimationFrame ||
function(timer) {
return $timeout.cancel(timer);
};
return function(fn) {
var id = requestAnimationFrame(fn);
return function() {
cancelAnimationFrame(id);
};
};
}])

.config(['$provide', '$animateProvider', function($provide, $animateProvider) {
var noop = angular.noop;
var forEach = angular.forEach;
Expand Down Expand Up @@ -872,7 +894,8 @@ angular.module('ngAnimate', ['ng'])
}
}]);

$animateProvider.register('', ['$window', '$sniffer', '$timeout', function($window, $sniffer, $timeout) {
$animateProvider.register('', ['$window', '$sniffer', '$timeout', '$$animateReflow',
function($window, $sniffer, $timeout, $$animateReflow) {
// Detect proper transitionend/animationend event names.
var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT;

Expand Down Expand Up @@ -917,11 +940,13 @@ angular.module('ngAnimate', ['ng'])
var parentCounter = 0;
var animationReflowQueue = [];
var animationElementQueue = [];
var animationTimer;
var cancelAnimationReflow;
var closingAnimationTime = 0;
var timeOut = false;
function afterReflow(element, callback) {
$timeout.cancel(animationTimer);
if(cancelAnimationReflow) {
cancelAnimationReflow();
}

animationReflowQueue.push(callback);

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

animationTimer = $timeout(function() {
cancelAnimationReflow = $$animateReflow(function() {
forEach(animationReflowQueue, function(fn) {
fn();
});
Expand All @@ -963,11 +988,11 @@ angular.module('ngAnimate', ['ng'])

animationReflowQueue = [];
animationElementQueue = [];
animationTimer = null;
cancelAnimationReflow = null;
lookupCache = {};
closingAnimationTime = 0;
animationCounter++;
}, 10, false);
});
}

function closeAllAnimations(elements, count) {
Expand Down
21 changes: 20 additions & 1 deletion src/ngMock/angular-mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,26 @@ angular.mock.TzDate = function (offset, timestamp) {
angular.mock.TzDate.prototype = Date.prototype;
/* jshint +W101 */

angular.module('ngAnimate').config(['$provide', function($provide) {
var reflowQueue = [];
$provide.value('$$animateReflow', function(fn) {
reflowQueue.push(fn);
return angular.noop;
});
$provide.decorator('$animate', function($delegate) {
$delegate.triggerReflow = function() {
if(reflowQueue.length === 0) {
throw new Error('No animation reflows present');
}
angular.forEach(reflowQueue, function(fn) {
fn();
});
reflowQueue = [];
};
return $delegate;
});
}]);

angular.mock.animate = angular.module('mock.animate', ['ng'])

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



if(window.jasmine || window.mocha) {

var currentSpec = null,
Expand Down
Loading

0 comments on commit 17b4b39

Please sign in to comment.