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.

enter image description here

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.

0
appatuck3r 8 marzec 2020, 14:16

2 odpowiedzi

Najlepsza odpowiedź

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

2
Kurt Hamilton 8 marzec 2020, 13:10

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>
1
SnorreDan 8 marzec 2020, 12:14