83 lines
2.2 KiB
TypeScript
83 lines
2.2 KiB
TypeScript
import {
|
|
ChangeDetectionStrategy,
|
|
Component,
|
|
Input,
|
|
OnChanges,
|
|
SimpleChanges,
|
|
ElementRef,
|
|
ViewChild,
|
|
AfterViewInit,
|
|
} from '@angular/core';
|
|
import { CommonModule, CurrencyPipe } from '@angular/common';
|
|
import { CountUp } from 'countup.js';
|
|
|
|
@Component({
|
|
selector: 'app-animated-number',
|
|
standalone: true,
|
|
imports: [CommonModule, CurrencyPipe],
|
|
template: ` <span #numberElement>{{ formattedValue }}</span> `,
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
})
|
|
export class AnimatedNumberComponent implements OnChanges, AfterViewInit {
|
|
@Input() value = 0;
|
|
@Input() duration = 1;
|
|
@Input() ease = 'power1.out';
|
|
|
|
@ViewChild('numberElement') numberElement!: ElementRef;
|
|
|
|
private countUp: CountUp | null = null;
|
|
private previousValue = 0;
|
|
formattedValue = '0,00 €';
|
|
|
|
ngAfterViewInit(): void {
|
|
this.initializeCountUp();
|
|
if (this.countUp && this.value !== 0) {
|
|
this.countUp.start(() => {
|
|
this.previousValue = this.value;
|
|
});
|
|
}
|
|
}
|
|
|
|
ngOnChanges(changes: SimpleChanges): void {
|
|
if (changes['value']) {
|
|
if (this.countUp) {
|
|
const endVal = this.value;
|
|
|
|
this.countUp.update(endVal);
|
|
this.previousValue = endVal;
|
|
} else {
|
|
this.formattedValue = new Intl.NumberFormat('de-DE', {
|
|
style: 'currency',
|
|
currency: 'EUR',
|
|
minimumFractionDigits: 2,
|
|
maximumFractionDigits: 2,
|
|
}).format(this.value);
|
|
}
|
|
}
|
|
}
|
|
|
|
private initializeCountUp(): void {
|
|
if (this.numberElement) {
|
|
this.countUp = new CountUp(this.numberElement.nativeElement, this.value, {
|
|
startVal: this.previousValue,
|
|
duration: this.duration,
|
|
easingFn: (t, b, c, d) => {
|
|
if (this.ease === 'power1.out') {
|
|
return c * (1 - Math.pow(1 - t / d, 1)) + b;
|
|
}
|
|
return c * (t / d) + b;
|
|
},
|
|
formattingFn: (value) => {
|
|
const formatted = new Intl.NumberFormat('de-DE', {
|
|
style: 'currency',
|
|
currency: 'EUR',
|
|
minimumFractionDigits: 2,
|
|
maximumFractionDigits: 2,
|
|
}).format(value);
|
|
this.formattedValue = formatted;
|
|
return formatted;
|
|
},
|
|
});
|
|
}
|
|
}
|
|
}
|