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

Commit

Permalink
fix($animate): ensure keyframe animations are blocked around the reflow
Browse files Browse the repository at this point in the history
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
  • Loading branch information
matsko committed Nov 22, 2013
1 parent 062fbed commit 6760d7a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/ngAnimate/animate.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -1025,13 +1027,21 @@ 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) {
node.style[prop] = '';
}
}

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) {
Expand Down Expand Up @@ -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) {
Expand Down
25 changes: 25 additions & 0 deletions test/ngAnimate/animateSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}));
});

0 comments on commit 6760d7a

Please sign in to comment.