Время CountDown в угловом 2
Я хочу иметь обратный отсчет даты следующим образом:
http://codepen.io/garethdweaver/pen/eNpWBb
но в угловом 2 я нашел этот plunkr, который добавляет 1 к числу каждые 500 миллисекунд:
https://plnkr.co/edit/pVMEbbGSzMwSBS4XEXJI?p=preview
это код:
import {Component,Input} from 'angular2/core';
import {Observable} from 'rxjs/Rx';
@Component({
selector: 'my-app',
template: '
<div>
{{message}}
</div>
'
})
export class AppComponent {
constructor() {
Observable.interval(1000)
.map((x) => x+1)
.subscribe((x) => {
this.message = x;
}):
}
}
Но я хочу, чтобы дата заняла одну секунду, пока не достигли 0.
Ответы
Ответ 1
import { Component, NgOnInit, ElementRef, OnInit, OnDestroy } from 'angular2/core';
import { Observable, Subscription } from 'rxjs/Rx';
@Component({
selector: 'my-app',
template: '
<div>
{{message}}
</div>
'
})
export class AppComponent implements OnInit, OnDestroy {
private future: Date;
private futureString: string;
private counter$: Observable<number>;
private subscription: Subscription;
private message: string;
constructor(elm: ElementRef) {
this.futureString = elm.nativeElement.getAttribute('inputDate');
}
dhms(t) {
var days, hours, minutes, seconds;
days = Math.floor(t / 86400);
t -= days * 86400;
hours = Math.floor(t / 3600) % 24;
t -= hours * 3600;
minutes = Math.floor(t / 60) % 60;
t -= minutes * 60;
seconds = t % 60;
return [
days + 'd',
hours + 'h',
minutes + 'm',
seconds + 's'
].join(' ');
}
ngOnInit() {
this.future = new Date(this.futureString);
this.counter$ = Observable.interval(1000).map((x) => {
return Math.floor((this.future.getTime() - new Date().getTime()) / 1000);
});
this.subscription = this.counter$.subscribe((x) => this.message = this.dhms(x));
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
}
HTML:
<my-app inputDate="January 1, 2018 12:00:00">Loading...</my-app>
Ответ 2
Сделал несколько изменений в ответе Джоннифиттицио. fooobar.com/questions/7287652/...
'
import {Observable} from 'rxjs/Rx';
import {Component, OnInit} from '@angular/core';
export class TimerComponent implements OnInit {
private _trialEndsAt;
private _diff: number;
private _days: number;
private _hours: number;
private _minutes: number;
private _seconds: number;
constructor() {}
ngOnInit() {
this._trialEndsAt = "2017-02-28";
Observable.interval(1000).map((x) => {
this._diff = Date.parse(this._trialEndsAt) - Date.parse(new Date().toString());
}).subscribe((x) => {
this._days = this.getDays(this._diff);
this._hours = this.getHours(this._diff);
this._minutes = this.getMinutes(this._diff);
this._seconds = this.getSeconds(this._diff);
});
}
getDays(t){
return Math.floor( t/(1000*60*60*24) );
}
getHours(t){
return Math.floor( (t/(1000*60*60)) % 24 );
}
getMinutes(t){
return Math.floor( (t/1000/60) % 60 );
}
getSeconds(t){
return Math.floor( (t/1000) % 60 );
}
} '
Ответ 3
Это немного упрощенная версия с жестко запрограммированной датой и возврат четырех различных выходов (дней - часов - минут - секунд), которые можно легко добавить в четыре окна:
export class HomePage {
// Hardcoded date
private eventDate: Date = new Date(2018, 9, 22);
private diff: number;
private countDownResult: number;
private days: number;
private hours: number;
private minutes: number;
private seconds: number;
constructor(public navCtrl: NavController ) {
Observable.interval(1000).map((x) => {
this.diff = Math.floor((this.eventDate.getTime() - new Date().getTime()) / 1000);
}).subscribe((x) => {
this.days = this.getDays(this.diff);
this.hours = this.getHours(this.diff);
this.minutes = this.getMinutes(this.diff);
this.seconds = this.getSeconds(this.diff);
});
}
getDays(t){
var days;
days = Math.floor(t / 86400);
return days;
}
getHours(t){
var days, hours;
days = Math.floor(t / 86400);
t -= days * 86400;
hours = Math.floor(t / 3600) % 24;
return hours;
}
getMinutes(t){
var days, hours, minutes;
days = Math.floor(t / 86400);
t -= days * 86400;
hours = Math.floor(t / 3600) % 24;
t -= hours * 3600;
minutes = Math.floor(t / 60) % 60;
return minutes;
}
getSeconds(t){
var days, hours, minutes, seconds;
days = Math.floor(t / 86400);
t -= days * 86400;
hours = Math.floor(t / 3600) % 24;
t -= hours * 3600;
minutes = Math.floor(t / 60) % 60;
t -= minutes * 60;
seconds = t % 60;
return seconds;
}
}
Ответ 4
Я думал, что имеет смысл создавать таймер как услугу, поэтому я могу иметь большую гибкость при создании своих просмотров (используйте возвращаемую модель времени, как вы хотите, в своих компонентах). Он создает новый наблюдаемый при подписке, поэтому каждый абонент получает свое собственное наблюдение. Короче говоря, вы можете создать столько таймеров одновременно с этой услугой, сколько хотите. Обязательно включите эту службу в свой массив поставщиков приложений, чтобы вы могли использовать ее в своем приложении.
Обслуживание:
import { Injectable } from '@angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/defer';
import 'rxjs/add/observable/interval';
import 'rxjs/add/operator/map';
export interface Time {
days: number;
hours: number;
minutes: number;
seconds: number;
}
@Injectable()
export class TimerService {
constructor() { }
private createTimeObject(date: Date): Time {
const now = new Date().getTime();
const distance = date.getTime() - now;
let time: Time = {days: 0, hours: 0, minutes: 0, seconds: 0};
time.days = Math.floor(distance / (1000 * 60 * 60 * 24));
time.hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
time.minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
time.seconds = Math.floor((distance % (1000 * 60)) / 1000);
return time;
}
timer(date: Date): Observable<Time> {
return Observable.interval(1000)
.map(() => this.createTimeObject(date))
}
}
Теперь используйте его в компоненте:
import {Component, OnInit} from '@angular/core';
import {Time, TimerService} from '../timer.service';
@Component({
selector: 'app-timer',
template: '
<ng-container *ngIf="time1$ | async as time1"
<pre>{{time1.days}}days {{time1.hours}}hours {{time1.minutes}} minutes {{time1.seconds}}seconds<pre>
<br>
<ng-container>
<ng-container *ngIf="time2$ | async as time2"
<pre>{{time2.days}}days {{time2.hours}}hours {{time2.minutes}} minutes {{time2.seconds}}seconds<pre>
<br>
<ng-container>
'
})
export class TimerComponent implements OnInit {
time1$: Observable<Time>;
time2$: Observable<Time>;
constructor(private timerService: TimerService) {}
ngOnInit() {
this.time1$ = this.timerService.timer(new Date('June 4, 2020 15:37:25'))
this.time2$ = this.timerService.timer(new Date('August 9, 2041 15:37:25'))
}
Ответ 5
ОБНОВЛЕНО для RXJS 5.5 +
import {map} from 'rxjs/internal/operators';
import { Component, OnInit } from '@angular/core';
import {interval, Observable} from 'rxjs';
@Component({
selector: 'app-countdown',
templateUrl: './countdown.component.html',
styleUrls: ['./countdown.component.css']
})
export class CountdownComponent implements OnInit {
private _trialEndsAt;
private _diff: number;
private _days: number;
private _hours: number;
private _minutes: number;
private _seconds: number;
constructor() {}
ngOnInit() {
this._trialEndsAt = "2017-02-28";
interval(3000).pipe(
map((x) => {this._diff = Date.parse(this._trialEndsAt) - Date.parse(new Date().toString());
})).subscribe((x) => {
this._days = this.getDays(this._diff);
this._hours = this.getHours(this._diff);
this._minutes = this.getMinutes(this._diff);
this._seconds = this.getSeconds(this._diff);
});
}
getDays(t) {
return Math.floor( t / (1000 * 60 * 60 * 24) );
}
getHours(t) {
return Math.floor( (t / (1000 * 60 * 60)) % 24 );
}
getMinutes(t) {
return Math.floor( (t / 1000 / 60) % 60 );
}
getSeconds(t) {
return Math.floor( (t / 1000) % 60 );
}
}
Ответ 6
Вот решение, которое я недавно придумал в своем проекте. Он проверяет время открытия ворот события и время основного события того же события. Это использует Momentjs.
У меня есть код в функции onChanges в случае изменения времени события в моей firebase, что очень маловероятно, но мне нравится тот факт, что он может забрать его и обновить на лету.
Компонент:
import { Component, OnInit, Input, OnChanges } from '@angular/core';
import { Observable } from "rxjs/Rx"
import { RoundService } from '../../round.service'
import * as moment from 'moment-timezone';
@Component({
selector: 'race-countdown',
templateUrl: './race-countdown.component.html',
styleUrls: ['./race-countdown.component.scss']
})
export class RaceCountdownComponent implements OnChanges,OnInit{
@Input() activeRound;
public time:number;
public timeToGates:number;
public timeToMains:number;
public countDown:Observable<any>;
public currentUnix = moment().unix();
constructor(private rs:RoundService) { }
ngOnChanges() {
this.timeToGates = this.activeRound.gateOpenUnix - this.currentUnix;
this.timeToMains = this.activeRound.mainEventUnix - this.currentUnix;
if(this.timeToGates < 0)
this.time = this.timeToMains
else
this.time = this.timeToGates
}
ngOnInit() {
this.countDown = Observable.interval(1000)
.map(res=>{ return this.time = this.time-1 })
.map(res=> {
let timeLeft = moment.duration(res, 'seconds');
let string:string = '';
// Days.
if(timeLeft.days() > 0)
string += timeLeft.days() + ' Days'
// Hours.
if(timeLeft.hours() > 0)
string += ' ' + timeLeft.hours() + ' Hours'
// Minutes.
if(timeLeft.minutes() > 0)
string += ' ' + timeLeft.minutes() + ' Mins'
// Seconds.
string += ' ' + timeLeft.seconds();
return string;
})
}
}
HTML:
<span>{{countDown | async}}</span>
Производит: "2 дня 6 часов 59 мин 42" и т.д.