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

Commit 32ad292

Browse files
committed
refactor($animate): use CSS3 transition/animation events instead of $timeouts to track ongoing animations
Closes #3629 Closes #3874
1 parent e12e584 commit 32ad292

File tree

2 files changed

+80
-68
lines changed

2 files changed

+80
-68
lines changed

src/ngAnimate/animate.js

+18-13
Original file line numberDiff line numberDiff line change
@@ -549,13 +549,16 @@ angular.module('ngAnimate', ['ng'])
549549
//one day all browsers will have these properties
550550
var w3cAnimationProp = 'animation';
551551
var w3cTransitionProp = 'transition';
552+
var w3cAnimationEvent = 'animationend';
553+
var w3cTransitionEvent = 'transitionend';
552554

553555
//but some still use vendor-prefixed styles
554556
var vendorAnimationProp = $sniffer.vendorPrefix + 'Animation';
555557
var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition';
558+
var vendorAnimationEvent = $sniffer.vendorPrefix.toLowerCase() + 'AnimationEnd';
559+
var vendorTransitionEvent = $sniffer.vendorPrefix.toLowerCase() + 'TransitionEnd';
556560

557561
var durationKey = 'Duration',
558-
delayKey = 'Delay',
559562
propertyKey = 'Property',
560563
animationIterationCountKey = 'IterationCount',
561564
ELEMENT_NODE = 1;
@@ -584,17 +587,12 @@ angular.module('ngAnimate', ['ng'])
584587
element.addClass(className);
585588

586589
//we want all the styles defined before and after
587-
var duration = 0;
590+
var transitionTime = 0,
591+
animationTime = 0;
588592
forEach(element, function(element) {
589593
if (element.nodeType == ELEMENT_NODE) {
590594
var elementStyles = $window.getComputedStyle(element) || {};
591595

592-
var transitionDelay = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + delayKey]),
593-
parseMaxTime(elementStyles[vendorTransitionProp + delayKey]));
594-
595-
var animationDelay = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + delayKey]),
596-
parseMaxTime(elementStyles[vendorAnimationProp + delayKey]));
597-
598596
var transitionDuration = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + durationKey]),
599597
parseMaxTime(elementStyles[vendorTransitionProp + durationKey]));
600598

@@ -607,16 +605,16 @@ angular.module('ngAnimate', ['ng'])
607605
1);
608606
}
609607

610-
duration = Math.max(animationDelay + animationDuration,
611-
transitionDelay + transitionDuration,
612-
duration);
608+
transitionTime = Math.max(transitionDuration, transitionTime);
609+
animationTime = Math.max(animationDuration, animationTime);
613610
}
614611
});
615612

616613
/* there is no point in performing a reflow if the animation
617614
timeout is empty (this would cause a flicker bug normally
618615
in the page */
619-
if(duration > 0) {
616+
var totalTime = Math.max(transitionTime,animationTime);
617+
if(totalTime > 0) {
620618
var node = element[0];
621619

622620
//temporarily disable the transition so that the enter styles
@@ -635,12 +633,15 @@ angular.module('ngAnimate', ['ng'])
635633
node.style[vendorTransitionProp + propertyKey] = '';
636634
element.addClass(activeClassName);
637635

638-
$timeout(done, duration * 1000, false);
636+
var css3AnimationEvents = [w3cAnimationEvent, vendorAnimationEvent,
637+
w3cTransitionEvent, vendorTransitionEvent].join(' ');
638+
element.on(css3AnimationEvents, onAnimationProgress);
639639

640640
//this will automatically be called by $animate so
641641
//there is no need to attach this internally to the
642642
//timeout done method
643643
return function onEnd(cancelled) {
644+
element.off(css3AnimationEvents, onAnimationProgress);
644645
element.removeClass(className);
645646
element.removeClass(activeClassName);
646647

@@ -657,6 +658,10 @@ angular.module('ngAnimate', ['ng'])
657658
done();
658659
}
659660

661+
function onAnimationProgress(event) {
662+
event.originalEvent.elapsedTime >= totalTime && done();
663+
}
664+
660665
function parseMaxTime(str) {
661666
var total = 0, values = angular.isString(str) ? str.split(/\s*,\s*/) : [];
662667
forEach(values, function(value) {

0 commit comments

Comments
 (0)