fix($animate): ensure keyframe animations are blocked around the reflow

Keyframe animations trigger on the first CSS class and not the second.
This may cause a slight flicker during a stagger animation since the
animation has already started before the stagger delay is considered.
This fix ensures that the animation is blocked until the active animation
starts which allows for staggering animations to take over properly.

Closes #5018
This commit is contained in:
Matias Niemelä 2013-11-19 00:21:48 -05:00
parent 062fbed8fc
commit 6760d7a315
2 changed files with 37 additions and 0 deletions

View file

@ -1002,6 +1002,8 @@ angular.module('ngAnimate', ['ng'])
element.addClass(NG_ANIMATE_FALLBACK_CLASS_NAME);
activeClassName += NG_ANIMATE_FALLBACK_ACTIVE_CLASS_NAME + ' ';
blockTransitions(element);
} else {
blockKeyframeAnimations(element);
}
forEach(className.split(' '), function(klass, i) {
@ -1025,6 +1027,10 @@ angular.module('ngAnimate', ['ng'])
element[0].style[TRANSITION_PROP + PROPERTY_KEY] = 'none';
}
function blockKeyframeAnimations(element) {
element[0].style[ANIMATION_PROP] = 'none 0s';
}
function unblockTransitions(element) {
var node = element[0], prop = TRANSITION_PROP + PROPERTY_KEY;
if(node.style[prop] && node.style[prop].length > 0) {
@ -1032,6 +1038,10 @@ angular.module('ngAnimate', ['ng'])
}
}
function unblockKeyframeAnimations(element) {
element[0].style[ANIMATION_PROP] = '';
}
function animateRun(element, className, activeAnimationComplete) {
var data = element.data(NG_ANIMATE_CSS_DATA_KEY);
if(!element.hasClass(className) || !data) {
@ -1059,6 +1069,8 @@ angular.module('ngAnimate', ['ng'])
style += CSS_PREFIX + 'transition-property: ' + propertyStyle + ', ' + fallbackProperty + '; ';
style += CSS_PREFIX + 'transition-duration: ' + timings.transitionDurationStyle + ', ' + timings.transitionDuration + 's; ';
}
} else {
unblockKeyframeAnimations(element);
}
if(ii > 0) {

View file

@ -2696,4 +2696,29 @@ describe("ngAnimate", function() {
expect(capturedProperty).not.toBe('none');
}));
it('should block and unblock keyframe animations around the reflow operation',
inject(function($rootScope, $compile, $rootElement, $document, $animate, $sniffer, $timeout) {
if (!$sniffer.animations) return;
$animate.enabled(true);
ss.addRule('.cross-animation', '-webkit-animation:1s my_animation;' +
'animation:1s my_animation;');
var element = $compile('<div class="cross-animation"></div>')($rootScope);
$rootElement.append(element);
jqLite($document[0].body).append($rootElement);
var node = element[0];
var animationKey = $sniffer.vendorPrefix == 'Webkit' ? 'WebkitAnimation' : 'animation';
$animate.addClass(element, 'trigger-class');
expect(node.style[animationKey]).toContain('none');
$timeout.flush();
expect(node.style[animationKey]).not.toContain('none');
}));
});