In this demo the dashOffset
property is used to trigger the dash-offset
animation.
So for example if we enter a new percentage in the input field we see the animation is triggered. The code that updates the dashOffset
state looks like this:
@Input({ transform: (p: string) => parseInt(p) })
set percentage(p: number) {
this.percentageState = p;
if (!this.firstAnimation) {
if (!!p) {
this.dashOffset = this.calculateDashOffset(this.percentageState);
} else {
this.dashOffset = undefined;
}
}
If it's not the first animation, then the dashOffset
state is calculated and this triggers the animation.
If it is the firstAnimation
then dashOffset
state is set in ngAfterViewInit
like this:
ngAfterViewInit() {
if (this.firstAnimation) {
this.dashOffset = this.calculateDashOffset(this.percentageState);
this.firstAnimation = false;
console.log(`The dash offset is ${this.dashOffset}`);
}
}
However this does not trigger the animation.
Where in the component lifecycle should we initialize an animation trigger in order to trigger the first animation?
Some things you can do:
First: You set changeDetection: ChangeDetectionStrategy.OnPush
, so you need to push any changes. Do it like this:
constructor(private ngz: NgZone, private changeRef: ChangeDetectorRef) {}
private firstAnimation: boolean = true;
ngAfterViewInit() {
if (this.firstAnimation) {
this.dashOffset = this.calculateDashOffset(this.percentageState);
this.firstAnimation = false;
this.changeRef.detectChanges();
}
}
Then easily set the percent in the main component, which gives the data to the cicle itself:
ngOnInit() {
this.control.valueChanges.subscribe((percent: any) => {
console.log(percent);
percent = parseInt(percent);
percent = !!percent ? percent : 100;
percent = isNaN(percent) ? 100 : percent;
percent = percent < 0 ? 0 : percent;
percent - percent > 100 ? 100 : percent;
this.percentage = percent;
});
setTimeout(() => {
this.percentage = 20;
},1)
}
The setTimeout
add the change into a new render frame and the animation works on start, and on every changing.