mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-16 23:30:23 +00:00
fix($animate): ensure staggering animations understand multiple delay values
This commit is contained in:
parent
e53ff431e1
commit
41a2d5b30f
2 changed files with 151 additions and 12 deletions
|
|
@ -789,7 +789,8 @@ angular.module('ngAnimate', ['ng'])
|
|||
var data = cacheKey ? lookupCache[cacheKey] : null;
|
||||
if(!data) {
|
||||
var transitionDuration = 0, transitionDelay = 0,
|
||||
animationDuration = 0, animationDelay = 0;
|
||||
animationDuration = 0, animationDelay = 0,
|
||||
transitionDelayStyle, animationDelayStyle;
|
||||
|
||||
//we want all the styles defined before and after
|
||||
forEach(element, function(element) {
|
||||
|
|
@ -799,9 +800,13 @@ angular.module('ngAnimate', ['ng'])
|
|||
transitionDuration = Math.max(parseMaxTime(elementStyles[transitionProp + durationKey]), transitionDuration);
|
||||
|
||||
if(!onlyCheckTransition) {
|
||||
transitionDelay = Math.max(parseMaxTime(elementStyles[transitionProp + delayKey]), transitionDelay);
|
||||
transitionDelayStyle = elementStyles[transitionProp + delayKey];
|
||||
|
||||
animationDelay = Math.max(parseMaxTime(elementStyles[animationProp + delayKey]), animationDelay);
|
||||
transitionDelay = Math.max(parseMaxTime(transitionDelayStyle), transitionDelay);
|
||||
|
||||
animationDelayStyle = elementStyles[animationProp + delayKey];
|
||||
|
||||
animationDelay = Math.max(parseMaxTime(animationDelayStyle), animationDelay);
|
||||
|
||||
var aDuration = parseMaxTime(elementStyles[animationProp + durationKey]);
|
||||
|
||||
|
|
@ -815,9 +820,11 @@ angular.module('ngAnimate', ['ng'])
|
|||
});
|
||||
data = {
|
||||
total : 0,
|
||||
transitionDelayStyle: transitionDelayStyle,
|
||||
transitionDelay : transitionDelay,
|
||||
animationDelay : animationDelay,
|
||||
transitionDuration : transitionDuration,
|
||||
animationDelayStyle: animationDelayStyle,
|
||||
animationDelay : animationDelay,
|
||||
animationDuration : animationDuration
|
||||
};
|
||||
if(cacheKey) {
|
||||
|
|
@ -905,16 +912,25 @@ angular.module('ngAnimate', ['ng'])
|
|||
|
||||
if(timings.transitionDuration > 0) {
|
||||
node.style[transitionProp + propertyKey] = '';
|
||||
if(ii > 0 && stagger.transitionDelay > 0 && stagger.transitionDuration === 0) {
|
||||
formerStyle = applyStyle(node, prefix + 'transition-delay: ' +
|
||||
(ii * stagger.transitionDelay + timings.transitionDelay) + 's');
|
||||
}
|
||||
|
||||
if(ii > 0) {
|
||||
var staggerStyle = '';
|
||||
if(stagger.transitionDelay > 0 && stagger.transitionDuration === 0) {
|
||||
staggerStyle += prefix + 'transition-delay: ' +
|
||||
prepareStaggerDelay(timings.transitionDelayStyle, stagger.transitionDelay, ii) + '; ';
|
||||
}
|
||||
|
||||
if(stagger.animationDelay > 0 && stagger.animationDuration === 0) {
|
||||
staggerStyle += prefix + 'animation-delay: ' +
|
||||
prepareStaggerDelay(timings.animationDelayStyle, stagger.animationDelay, ii) + '; ';
|
||||
}
|
||||
|
||||
if(staggerStyle.length > 0) {
|
||||
formerStyle = applyStyle(node, staggerStyle);
|
||||
}
|
||||
}
|
||||
|
||||
if(ii > 0 && stagger.animationDelay > 0 && stagger.animationDuration === 0) {
|
||||
formerStyle = applyStyle(node, prefix + 'animation-delay: ' +
|
||||
(ii * stagger.animationDelay + timings.animationDelay) + 's');
|
||||
}
|
||||
element.addClass(activeClassName);
|
||||
});
|
||||
|
||||
|
|
@ -948,6 +964,15 @@ angular.module('ngAnimate', ['ng'])
|
|||
done();
|
||||
}
|
||||
|
||||
function prepareStaggerDelay(delayStyle, staggerDelay, index) {
|
||||
var style = '';
|
||||
angular.forEach(delayStyle.split(','), function(val, i) {
|
||||
style += (i > 0 ? ',' : '') +
|
||||
(index * staggerDelay + parseInt(val, 10)) + 's';
|
||||
});
|
||||
return style;
|
||||
}
|
||||
|
||||
function onAnimationProgress(event) {
|
||||
event.stopPropagation();
|
||||
var ev = event.originalEvent || event;
|
||||
|
|
|
|||
|
|
@ -697,7 +697,7 @@ describe("ngAnimate", function() {
|
|||
|
||||
ss.addRule('.ani.ng-enter, .ani.ng-leave, .ani-fake.ng-enter, .ani-fake.ng-leave',
|
||||
'-webkit-animation:1s my_animation;' +
|
||||
'transition:1s my_animation;');
|
||||
'animation:1s my_animation;');
|
||||
|
||||
ss.addRule('.ani.ng-enter-stagger, .ani.ng-leave-stagger',
|
||||
'-webkit-animation-delay:0.1s;' +
|
||||
|
|
@ -747,6 +747,40 @@ describe("ngAnimate", function() {
|
|||
expect(elements[3].attr('style')).not.toMatch(/animation-delay: 0\.3\d*s/);
|
||||
expect(elements[4].attr('style')).not.toMatch(/animation-delay: 0\.4\d*s/);
|
||||
}));
|
||||
|
||||
it("should stagger items when multiple animation durations/delays are defined",
|
||||
inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement) {
|
||||
|
||||
if(!$sniffer.transitions) return;
|
||||
|
||||
$animate.enabled(true);
|
||||
|
||||
ss.addRule('.ani.ng-enter, .ani.ng-leave',
|
||||
'-webkit-animation:my_animation 1s 1s, your_animation 1s 2s;' +
|
||||
'animation:my_animation 1s 1s, your_animation 1s 2s;');
|
||||
|
||||
ss.addRule('.ani.ng-enter-stagger, .ani.ng-leave-stagger',
|
||||
'-webkit-animation-delay:0.1s;' +
|
||||
'animation-delay:0.1s;');
|
||||
|
||||
var container = $compile(html('<div></div>'))($rootScope);
|
||||
|
||||
var elements = [];
|
||||
for(var i = 0; i < 4; i++) {
|
||||
var newScope = $rootScope.$new();
|
||||
var element = $compile('<div class="ani"></div>')(newScope);
|
||||
$animate.enter(element, container);
|
||||
elements.push(element);
|
||||
};
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
|
||||
expect(elements[0].attr('style')).toBeFalsy();
|
||||
expect(elements[1].attr('style')).toMatch(/animation-delay: 1\.1\d*s,\s*2\.1\d*s/);
|
||||
expect(elements[2].attr('style')).toMatch(/animation-delay: 1\.2\d*s,\s*2\.2\d*s/);
|
||||
expect(elements[3].attr('style')).toMatch(/animation-delay: 1\.3\d*s,\s*2\.3\d*s/);
|
||||
}));
|
||||
});
|
||||
|
||||
describe("Transitions", function() {
|
||||
|
|
@ -950,7 +984,87 @@ describe("ngAnimate", function() {
|
|||
expect(elements[3].attr('style')).not.toMatch(/transition-delay: 0\.3\d*s/);
|
||||
expect(elements[4].attr('style')).not.toMatch(/transition-delay: 0\.4\d*s/);
|
||||
}));
|
||||
|
||||
it("should stagger items when multiple transition durations/delays are defined",
|
||||
inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement) {
|
||||
|
||||
if(!$sniffer.transitions) return;
|
||||
|
||||
$animate.enabled(true);
|
||||
|
||||
ss.addRule('.ani.ng-enter, .ani.ng-leave',
|
||||
'-webkit-transition:1s linear color 2s, 3s linear font-size 4s;' +
|
||||
'transition:1s linear color 2s, 3s linear font-size 4s;');
|
||||
|
||||
ss.addRule('.ani.ng-enter-stagger, .ani.ng-leave-stagger',
|
||||
'-webkit-transition-delay:0.1s;' +
|
||||
'transition-delay:0.1s;');
|
||||
|
||||
var container = $compile(html('<div></div>'))($rootScope);
|
||||
|
||||
var elements = [];
|
||||
for(var i = 0; i < 4; i++) {
|
||||
var newScope = $rootScope.$new();
|
||||
var element = $compile('<div class="ani"></div>')(newScope);
|
||||
$animate.enter(element, container);
|
||||
elements.push(element);
|
||||
};
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
|
||||
expect(elements[0].attr('style')).toBeFalsy();
|
||||
expect(elements[1].attr('style')).toMatch(/transition-delay: 2\.1\d*s,\s*4\.1\d*s/);
|
||||
expect(elements[2].attr('style')).toMatch(/transition-delay: 2\.2\d*s,\s*4\.2\d*s/);
|
||||
expect(elements[3].attr('style')).toMatch(/transition-delay: 2\.3\d*s,\s*4\.3\d*s/);
|
||||
}));
|
||||
});
|
||||
|
||||
it("should apply staggering to both transitions and keyframe animations when used within the same animation",
|
||||
inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement) {
|
||||
|
||||
if(!$sniffer.transitions) return;
|
||||
|
||||
$animate.enabled(true);
|
||||
|
||||
ss.addRule('.ani.ng-enter, .ani.ng-leave',
|
||||
'-webkit-animation:my_animation 1s 1s, your_animation 1s 2s;' +
|
||||
'animation:my_animation 1s 1s, your_animation 1s 2s;' +
|
||||
'-webkit-transition:1s linear all 0s;' +
|
||||
'transition:1s linear all 1s;');
|
||||
|
||||
ss.addRule('.ani.ng-enter-stagger, .ani.ng-leave-stagger',
|
||||
'-webkit-transition-delay:0.1s;' +
|
||||
'transition-delay:0.1s;' +
|
||||
'-webkit-animation-delay:0.2s;' +
|
||||
'animation-delay:0.2s;');
|
||||
|
||||
var container = $compile(html('<div></div>'))($rootScope);
|
||||
|
||||
var elements = [];
|
||||
for(var i = 0; i < 3; i++) {
|
||||
var newScope = $rootScope.$new();
|
||||
var element = $compile('<div class="ani"></div>')(newScope);
|
||||
$animate.enter(element, container);
|
||||
elements.push(element);
|
||||
};
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
|
||||
expect(elements[0].attr('style')).toBeFalsy();
|
||||
|
||||
expect(elements[1].attr('style')).toMatch(/transition-delay:\s+1.1\d*/);
|
||||
expect(elements[1].attr('style')).toMatch(/animation-delay: 1\.2\d*s,\s*2\.2\d*s/);
|
||||
|
||||
expect(elements[2].attr('style')).toMatch(/transition-delay:\s+1.2\d*/);
|
||||
expect(elements[2].attr('style')).toMatch(/animation-delay: 1\.4\d*s,\s*2\.4\d*s/);
|
||||
|
||||
for(var i = 0; i < 3; i++) {
|
||||
browserTrigger(elements[i],'transitionend', { timeStamp: Date.now() + 22000, elapsedTime: 22000 });
|
||||
expect(elements[i].attr('style')).toBeFalsy();
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
describe('animation evaluation', function () {
|
||||
|
|
|
|||
Loading…
Reference in a new issue