Skip to content

Commit bba2dae

Browse files
fix(animations): make sure that the useAnimation function delay is applied (#47468)
make sure that when an animation is used via the `useAnimation` function and a delay has been provided then that delay gets correctly applied (this PR is a follow up for #47285) PR Close #47468
1 parent fe6d33c commit bba2dae

File tree

2 files changed

+114
-25
lines changed

2 files changed

+114
-25
lines changed

packages/animations/browser/src/dsl/animation_timeline_builder.ts

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -183,32 +183,25 @@ export class AnimationTimelineBuilderVisitor implements AstVisitor {
183183
visitAnimateRef(ast: AnimateRefAst, context: AnimationTimelineContext): any {
184184
const innerContext = context.createSubContext(ast.options);
185185
innerContext.transformIntoNewTimeline();
186-
this._applyAnimateRefDelay(ast.animation, context, innerContext);
186+
this._applyAnimationRefDelays([ast.options, ast.animation.options], context, innerContext);
187187
this.visitReference(ast.animation, innerContext);
188188
context.transformIntoNewTimeline(innerContext.currentTimeline.currentTime);
189189
context.previousNode = ast;
190190
}
191191

192-
private _applyAnimateRefDelay(
193-
animation: ReferenceAst, context: AnimationTimelineContext,
192+
private _applyAnimationRefDelays(
193+
animationsRefsOptions: (AnimationOptions|null)[], context: AnimationTimelineContext,
194194
innerContext: AnimationTimelineContext) {
195-
const animationDelay = animation.options?.delay;
196-
197-
if (!animationDelay) {
198-
return;
199-
}
200-
201-
let animationDelayValue: number;
202-
203-
if (typeof animationDelay === 'string') {
204-
const interpolatedDelay =
205-
interpolateParams(animationDelay, animation.options?.params ?? {}, context.errors);
206-
animationDelayValue = resolveTimingValue(interpolatedDelay);
207-
} else {
208-
animationDelayValue = animationDelay;
195+
for (const animationRefOptions of animationsRefsOptions) {
196+
const animationDelay = animationRefOptions?.delay;
197+
if (animationDelay) {
198+
const animationDelayValue = typeof animationDelay === 'number' ?
199+
animationDelay :
200+
resolveTimingValue(interpolateParams(
201+
animationDelay, animationRefOptions?.params ?? {}, context.errors));
202+
innerContext.delayNextStep(animationDelayValue);
203+
}
209204
}
210-
211-
innerContext.delayNextStep(animationDelayValue);
212205
}
213206

214207
private _visitSubInstructions(

packages/core/test/animation/animation_integration_spec.ts

Lines changed: 102 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3923,13 +3923,57 @@ describe('animation tests', function() {
39233923
]);
39243924
});
39253925

3926-
it('should combine the delay specified in the animation with that of the caller', () => {
3926+
it('should apply the delay specified in the useAnimation call', () => {
3927+
const animationMetaData = animation([
3928+
style({color: 'red'}),
3929+
animate(550, style({color: 'green'})),
3930+
]);
3931+
3932+
@Component({
3933+
selector: 'cmp',
3934+
template: `
3935+
<div @anim *ngIf="exp">
3936+
</div>
3937+
`,
3938+
animations: [
3939+
trigger('anim', [transition(
3940+
':enter',
3941+
useAnimation(animationMetaData, {delay: 1500}),
3942+
)]),
3943+
]
3944+
})
3945+
class Cmp {
3946+
exp: boolean = false;
3947+
}
3948+
3949+
TestBed.configureTestingModule({declarations: [Cmp]});
3950+
3951+
const engine = TestBed.inject(ɵAnimationEngine);
3952+
const fixture = TestBed.createComponent(Cmp);
3953+
const cmp = fixture.componentInstance;
3954+
cmp.exp = true;
3955+
3956+
fixture.detectChanges();
3957+
engine.flush();
3958+
3959+
const players = getLog();
3960+
expect(players.length).toEqual(1);
3961+
const [player] = players;
3962+
expect(player.delay).toEqual(1500);
3963+
expect(player.duration).toEqual(550);
3964+
expect(player.keyframes).toEqual([
3965+
new Map<string, string|number>([['color', 'red'], ['offset', 0]]),
3966+
new Map<string, string|number>([['color', 'green'], ['offset', 1]]),
3967+
]);
3968+
});
3969+
3970+
it('should apply the delay specified in the useAnimation call using params', () => {
39273971
const animationMetaData = animation(
39283972
[
39293973
style({color: 'red'}),
3930-
animate(500, style({color: 'green'})),
3974+
animate(700, style({color: 'green'})),
39313975
],
3932-
{delay: 2000});
3976+
);
39333977

39343978
@Component({
39353979
selector: 'cmp',
@@ -3938,7 +3982,13 @@ describe('animation tests', function() {
39383982
</div>
39393983
`,
39403984
animations: [
3941-
trigger('anim', [transition(':enter', useAnimation(animationMetaData), {delay: 750})]),
3985+
trigger('anim', [transition(
3986+
':enter',
3987+
useAnimation(animationMetaData, {
3988+
delay: '{{useAnimationDelay}}ms',
3989+
params: {useAnimationDelay: 7500}
3990+
}),
3991+
)]),
39423992
]
39433993
})
39443994
class Cmp {
@@ -3958,13 +4008,59 @@ describe('animation tests', function() {
39584008
const players = getLog();
39594009
expect(players.length).toEqual(1);
39604010
const [player] = players;
3961-
expect(player.delay).toEqual(2750);
3962-
expect(player.duration).toEqual(500);
4011+
expect(player.delay).toEqual(7500);
4012+
expect(player.duration).toEqual(700);
39634013
expect(player.keyframes).toEqual([
39644014
new Map<string, string|number>([['color', 'red'], ['offset', 0]]),
39654015
new Map<string, string|number>([['color', 'green'], ['offset', 1]]),
39664016
]);
39674017
});
4018+
4019+
it('should combine the delays specified in the animation and the useAnimation with that of the caller',
4020+
() => {
4021+
const animationMetaData = animation(
4022+
[
4023+
style({color: 'red'}),
4024+
animate(567, style({color: 'green'})),
4025+
],
4026+
{delay: 1000});
4027+
4028+
@Component({
4029+
selector: 'cmp',
4030+
template: `
4031+
<div @anim *ngIf="exp">
4032+
</div>
4033+
`,
4034+
animations: [
4035+
trigger('anim', [transition(
4036+
':enter', useAnimation(animationMetaData, {delay: 34}),
4037+
{delay: 200})]),
4038+
]
4039+
})
4040+
class Cmp {
4041+
exp: boolean = false;
4042+
}
4043+
4044+
TestBed.configureTestingModule({declarations: [Cmp]});
4045+
4046+
const engine = TestBed.inject(ɵAnimationEngine);
4047+
const fixture = TestBed.createComponent(Cmp);
4048+
const cmp = fixture.componentInstance;
4049+
cmp.exp = true;
4050+
4051+
fixture.detectChanges();
4052+
engine.flush();
4053+
4054+
const players = getLog();
4055+
expect(players.length).toEqual(1);
4056+
const [player] = players;
4057+
expect(player.delay).toEqual(1234);
4058+
expect(player.duration).toEqual(567);
4059+
expect(player.keyframes).toEqual([
4060+
new Map<string, string|number>([['color', 'red'], ['offset', 0]]),
4061+
new Map<string, string|number>([['color', 'green'], ['offset', 1]]),
4062+
]);
4063+
});
39684064
});
39694065

39704066
it('should combine multiple errors together into one exception when an animation fails to be built',

0 commit comments

Comments
 (0)