fix(animations): do not delay style() values before a stagger() runs
Closes #17412
This commit is contained in:
parent
f1626574dd
commit
34f3832af9
|
@ -409,11 +409,12 @@ export class AnimationTimelineBuilderVisitor implements AstVisitor {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const timeline = context.currentTimeline;
|
||||||
if (delay) {
|
if (delay) {
|
||||||
context.currentTimeline.delayNextStep(delay);
|
timeline.delayNextStep(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
const startingTime = context.currentTimeline.currentTime;
|
const startingTime = timeline.currentTime;
|
||||||
ast.animation.visit(this, context);
|
ast.animation.visit(this, context);
|
||||||
context.previousNode = ast;
|
context.previousNode = ast;
|
||||||
|
|
||||||
|
@ -612,10 +613,19 @@ export class TimelineBuilder {
|
||||||
get currentTime() { return this.startTime + this.duration; }
|
get currentTime() { return this.startTime + this.duration; }
|
||||||
|
|
||||||
delayNextStep(delay: number) {
|
delayNextStep(delay: number) {
|
||||||
if (this.duration == 0) {
|
// in the event that a style() step is placed right before a stagger()
|
||||||
this.startTime += delay;
|
// and that style() step is the very first style() value in the animation
|
||||||
} else {
|
// then we need to make a copy of the keyframe [0, copy, 1] so that the delay
|
||||||
|
// properly applies the style() values to work with the stagger...
|
||||||
|
const hasPreStyleStep = this._keyframes.size == 1 && Object.keys(this._pendingStyles).length;
|
||||||
|
|
||||||
|
if (this.duration || hasPreStyleStep) {
|
||||||
this.forwardTime(this.currentTime + delay);
|
this.forwardTime(this.currentTime + delay);
|
||||||
|
if (hasPreStyleStep) {
|
||||||
|
this.snapshotCurrentStyles();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.startTime += delay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -529,6 +529,72 @@ export function main() {
|
||||||
expect(p3.duration).toEqual(4000);
|
expect(p3.duration).toEqual(4000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should properly apply pre styling before a stagger is issued', () => {
|
||||||
|
@Component({
|
||||||
|
selector: 'ani-cmp',
|
||||||
|
template: `
|
||||||
|
<div [@myAnimation]="exp">
|
||||||
|
<div *ngFor="let item of items" class="item">
|
||||||
|
{{ item }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
animations: [
|
||||||
|
trigger(
|
||||||
|
'myAnimation',
|
||||||
|
[
|
||||||
|
transition(
|
||||||
|
'* => go',
|
||||||
|
[
|
||||||
|
query(
|
||||||
|
':enter',
|
||||||
|
[
|
||||||
|
style({opacity: 0}),
|
||||||
|
stagger(
|
||||||
|
100,
|
||||||
|
[
|
||||||
|
animate(1000, style({opacity: 1})),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
})
|
||||||
|
class Cmp {
|
||||||
|
public exp: any;
|
||||||
|
public items: any[] = [0, 1, 2, 3, 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [Cmp]});
|
||||||
|
|
||||||
|
const engine = TestBed.get(ɵAnimationEngine);
|
||||||
|
const fixture = TestBed.createComponent(Cmp);
|
||||||
|
const cmp = fixture.componentInstance;
|
||||||
|
|
||||||
|
cmp.exp = 'go';
|
||||||
|
fixture.detectChanges();
|
||||||
|
engine.flush();
|
||||||
|
|
||||||
|
const players = getLog();
|
||||||
|
expect(players.length).toEqual(5);
|
||||||
|
|
||||||
|
for (let i = 0; i < players.length; i++) {
|
||||||
|
const player = players[i];
|
||||||
|
const kf = player.keyframes;
|
||||||
|
const limit = kf.length - 1;
|
||||||
|
const staggerDelay = 100 * i;
|
||||||
|
const duration = 1000 + staggerDelay;
|
||||||
|
|
||||||
|
expect(kf[0]).toEqual({opacity: '0', offset: 0});
|
||||||
|
if (limit > 1) {
|
||||||
|
const offsetAtStaggerDelay = staggerDelay / duration;
|
||||||
|
expect(kf[1]).toEqual({opacity: '0', offset: offsetAtStaggerDelay});
|
||||||
|
}
|
||||||
|
expect(kf[limit]).toEqual({opacity: '1', offset: 1});
|
||||||
|
expect(player.duration).toEqual(duration);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('should apply a full stagger step delay if the timing data is left undefined', () => {
|
it('should apply a full stagger step delay if the timing data is left undefined', () => {
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ani-cmp',
|
selector: 'ani-cmp',
|
||||||
|
|
Loading…
Reference in New Issue