Próbuję wyświetlić licznik czasu, jak pokazano poniżej na tym zrzucie ekranu. Ciągle liczyć, aby pokazać, jak długo od tego wpisu.
Nie mogłem znaleźć zbyt wielu możliwości zrobienia tego w Angular. Znalazłem to rozwiązanie w Angular JS. https://siddii.github.io/angular-timer/ Potrzebuję dokładnie minutnika lubię to. Ale nie byłem w stanie przenieść go do Angulara lub nie mogłem. Wypróbowałem więc inne dostępne alternatywy i okazało się, że nadal nie działają.
https://www.npmjs.com/package/ng2-simple-timer
https://www.npmjs.com/package/ngx-timer
Najbliżej mnie był ten ngx-timer Countup-timer. https://www.npmjs.com/package/ngx-timer licznik czasu działa dobrze i może rozpocząć się od określonej daty, zgodnie z moim wymaganiem. startTimer (startDate). Ale ma znany problem, który wciąż pozostaje nierozwiązany, a mianowicie odnosi się do ostatniego znanego indeksu elementu timera, przez co tylko jeden timer działa na całej liście timerów.Możesz to zauważyć na powyższym zrzucie ekranu.
To znany błąd. https://github.com/Y4SHVINE/ngx-timer-lib/issues
Czy ktoś może mi pomóc w rozwiązaniu lub poprawieniu któregoś z tych rozwiązań, aby to zadziałało.
Dzięki.
2 odpowiedzi
Zrobiłbym to, pisząc funkcję zwracającą różnicę między aktualnym czasem a czasem utworzenia obiektu.
Moją początkową myślą było zwrócenie różnicy jako obiekt Date
, a następnie sformatowanie wyniku. Wkrótce napotkałem problemy podczas formatowania różnych zakresów czasowych, ponieważ data to nie to samo, co przedział czasu.
Więc zamiast próbować sformatować Date
, który udaje przedział czasowy, stworzyłbym własny interfejs.
export interface TimeSpan {
hours: number;
minutes: number;
seconds: number;
}
W ten sposób zachowujemy kontrolę nad obsługą okresów> = 1 dnia i unikamy problemów ze strefami czasowymi.
Użyłbym wykrywania zmian OnPush
, aby zachować kontrolę nad uruchomieniem wykrywania zmian:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {
constructor(private changeDetector: ChangeDetectorRef) {}
}
Następnie rozpocząłbym RxJS interval
w ngOnInit()
, upewniając się, że zrezygnuję z subskrypcji, gdy skończymy:
private destroyed$ = new Subject();
ngOnInit() {
interval(1000).subscribe(() => {
this.changeDetector.detectChanges();
});
}
ngOnDestroy() {
this.destroyed$.next();
this.destroyed$.complete();
}
Kod HTML pobierałby wtedy czas, który upłynął z funkcji w moim komponencie:
getElapsedTime(entry: Entry): TimeSpan {
let totalSeconds = Math.floor((new Date().getTime() - entry.created.getTime()) / 1000);
let hours = 0;
let minutes = 0;
let seconds = 0;
if (totalSeconds >= 3600) {
hours = Math.floor(totalSeconds / 3600);
totalSeconds -= 3600 * hours;
}
if (totalSeconds >= 60) {
minutes = Math.floor(totalSeconds / 60);
totalSeconds -= 60 * minutes;
}
seconds = totalSeconds;
return {
hours: hours,
minutes: minutes,
seconds: seconds
};
}
Ta funkcja rozpoczyna się od uzyskania całkowitej liczby sekund, które upłynęły od daty utworzenia, a następnie oblicza składniki godziny, minuty i sekundy.
Gdzie entry
jest obiektem, który zawiera instancję Date
wskazującą czas jej utworzenia. W moim demo używam tego interfejsu:
export interface Entry {
created: Date;
id: string;
}
Upływający przedział czasu można następnie pobrać dla każdej instancji wewnątrz *ngFor
w następujący sposób:
<span *ngIf="getElapsedTime(entry) as elapsed">
{{elapsed.hours}} h {{elapsed.minutes}} m {{elapsed.seconds}} s
</span>
DEMO: https://stackblitz.com/edit/angular-p1b9af
Możesz to zrobić z RxJS w ten sposób:
const startDate = new Date('2020-03-08 14:12:23');
timer(1000, 1000)
.pipe(
map((x: number) => {
const newDate = new Date(startDate.getTime());
newDate.setSeconds(newDate.getSeconds() + x);
return newDate;
})
)
.subscribe(t => this.myDate = t);
Następnie w swoim komponencie robisz:
<div>{{ mydate | date: "hh 'h' mm 'm' ss 's'" }}</div>