Angular is a popular front-end framework made by Google. Like other popular front-end frameworks, it uses a component-based architecture to structure apps.
In this article, we look at animation callback and keyframes.
Animation Callbacks
The animation trigger
emits callbacks when it starts and when it finishes.
For example, we can log the value of the event by writing the following code:
app.component.ts
:
import { Component, HostBinding } from "@angular/core";
import {
trigger,
transition,
style,
animate,
state
} from "@angular/animations";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
animations: [
trigger("openClose", [
state(
"true",
style({ height: "200px", opacity: 1, backgroundColor: "yellow" })
),
state(
"false",
style({ height: "100px", opacity: 0.5, backgroundColor: "green" })
),
transition("false <=> true", animate(500))
])
]
})
export class AppComponent {
onAnimationEvent(event: AnimationEvent) {
console.log(event);
}
}
app.component.html
:
<button (click)="show = !show">Toggle</button>
<div
[@openClose]="show ? true: false"
(@openClose.start)="onAnimationEvent($event)"
(@openClose.done)="onAnimationEvent($event)"
>
{{show ? 'foo' : ''}}
</div>
In the code above, we have:
(@openClose.start)="onAnimationEvent($event)"
(@openClose.done)="onAnimationEvent($event)"
to call the onAnimationEvent
callback when the animation begins and ends respectively.
Then in our onAnimationEvent
callback, we log the content of the event
parameter.
It’s useful for debugging since it provides information about the states and elements of the animation.
Keyframes
We can add keyframes to our animation to create animations that are more complex than 2 stage animations.
For example, we can write the following:
app.component.ts
:
import { Component } from "@angular/core";
import {
trigger,
transition,
style,
animate,
keyframes
} from "@angular/animations";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
animations: [
trigger("openClose", [
transition('true <=> false', [
animate('2s', keyframes([
style({ backgroundColor: 'blue' }),
style({ backgroundColor: 'red' }),
style({ backgroundColor: 'orange' })
]))
])
]
})
export class AppComponent {
onAnimationEvent(event: AnimationEvent) {
console.log(event);
}
}
app.component.html
:
<button (click)="show = !show">Toggle</button>
<div [@openClose]="show ? true: false">
{{show ? 'foo' : 'bar'}}
</div>
In the code above, we add keyframes with different styles in AppComponent
.
They’ll run in the order that they’re listed for the forward state transition and reverse for the reverse state transition.
Then when we click Toggle, we’ll see the color changes as the text changes.
Offset
Keyframes include an offset that defines the point in the animation where each style change occurs.
Offsets are relative measures from zero to one. They mark the beginning and end of the animation.
These are optional. Offsets are automatically assigned when they’re omitted.
For example, we can assign offsets as follows:
app.component.ts
:
import { Component } from "@angular/core";
import {
trigger,
transition,
style,
animate,
keyframes
} from "@angular/animations";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
animations: [
trigger("openClose", [
transition('true <=> false', [
animate('2s', keyframes([
style({ backgroundColor: 'blue', offset: 0 }),
style({ backgroundColor: 'red', offset: 0.6 }),
style({ backgroundColor: 'orange', offset: 1 })
]))
])
]
})
export class AppComponent {
onAnimationEvent(event: AnimationEvent) {
console.log(event);
}
}
app.component.html
:
<button (click)="show = !show">Toggle</button>
<div [@openClose]="show ? true: false">
{{show ? 'foo' : 'bar'}}
</div>
In the code above, we added offset
properties to our style
argument objects to change the timing of the color changes.
The color changes should shift slightly in timing compared to before.
Keyframes with a Pulsation
We can use keyframes to create a pulse effect by defining styles at a specific offset throughout the animation.
To add them, we can change the opacity of the keyframes as follows:
app.component.ts
:
import { Component } from "@angular/core";
import {
trigger,
transition,
style,
animate,
keyframes
} from "@angular/animations";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
animations: [
trigger("openClose", [
transition('true <=> false', [
animate('1s', keyframes ( [
style({ opacity: 0.1, offset: 0.1 }),
style({ opacity: 0.6, offset: 0.2 }),
style({ opacity: 1, offset: 0.5 }),
style({ opacity: 0.2, offset: 0.7 })
]))
])
]
})
export class AppComponent {
onAnimationEvent(event: AnimationEvent) {
console.log(event);
}
}
app.component.html
:
<button (click)="show = !show">Toggle</button>
<div [@openClose]="show ? true: false">
{{show ? 'foo' : 'bar'}}
</div>
In the code above, we have the style
argument objects that have the opacity
and offset
properties.
The opacity
difference will create a pulsating effect.
The offset
will change the timing of the opacity
changes.
Then when we click Toggle, we should see the pulsating effect.
Automatic Property Calculation with Wildcards
We can set CSS style properties to a wildcard to do automatic calculations.
For example, we can use wildcards as follows:
app.component.ts
:
import { Component } from "@angular/core";
import {
trigger,
transition,
style,
animate,
state
} from "@angular/animations";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
animations: [
trigger("openClose", [
state("in", style({ height: "*" })),
transition("true => false", [
style({ height: "*", backgroundColor: "pink" }),
animate(250, style({ height: 0 }))
]),
transition("false => true", [
style({ height: "*", backgroundColor: "yellow" }),
animate(250, style({ height: 0 }))
])
])
]
})
export class AppComponent {
onAnimationEvent(event: AnimationEvent) {
console.log(event);
}
}
app.component.html
:
<button (click)="show = !show">Toggle</button>
<div [@openClose]="show ? true: false">
{{show ? 'foo' : 'bar'}}
</div>
In the code above, we set the height
of the styles to a wildcard because we don’t want to set the height to a fixed height.
Then when we click Toggle, we see the color box grow and shrink as the animation runs.
Conclusion
We can add callbacks to our animation to debug our animations since we can log the values there.
To make more complex animations, we can use keyframes.
Offsets can be used to change the timing of the keyframes of the animation.
We can use wildcards to automatically set CSS style values.