Javascript 角度 2 中的时间倒计时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36461089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 19:06:51  来源:igfitidea点击:

Time CountDown in angular 2

javascriptangular

提问by Diego Unanue

I want to have a date countdown like this:

我想要一个这样的日期倒计时:

http://codepen.io/garethdweaver/pen/eNpWBb

http://codepen.io/garethdweaver/pen/eNpWBb

but in angular 2, I found this plunkr that adds 1 to a number each 500 miliseconds:

但是在 angular 2 中,我发现这个 plunkr 每 500 毫秒给一个数字加 1:

https://plnkr.co/edit/pVMEbbGSzMwSBS4XEXJI?p=preview

https://plnkr.co/edit/pVMEbbGSzMwSBS4XEXJI?p=preview

this is the code:

这是代码:

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;
              }):
  }
}

But I want to have a date taking one second until reach 0.

但我想要一个约会一秒钟直到达到 0。

回答by KnowHoper

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:

HTML:

 <my-app inputDate="January 1, 2018 12:00:00">Loading...</my-app>

回答by FrancescoMussi

This is a bit simplified version with hardcoded date and returning four different outputs (days - hours - minutes - seconds) that you can put nicely in four boxes:

这是一个带有硬编码日期并返回四个不同输出(天 - 小时 - 分钟 - 秒)的简化版本,您可以将它们很好地放入四个框中:

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){
        return Math.floor(t / 86400);
    }

    getHours(t){
        const days = Math.floor(t / 86400);
        t -= days * 86400;
        const hours = Math.floor(t / 3600) % 24;
        return hours;
    }

    getMinutes(t){
        const days = Math.floor(t / 86400);
        t -= days * 86400;
        const hours = Math.floor(t / 3600) % 24;
        t -= hours * 3600;
        const minutes = Math.floor(t / 60) % 60;
        return minutes;
    }

    getSeconds(t){
        const days = Math.floor(t / 86400);
        t -= days * 86400;
        const hours = Math.floor(t / 3600) % 24;
        t -= hours * 3600;
        const minutes = Math.floor(t / 60) % 60;
        t -= minutes * 60;
        const seconds = t % 60;
        return seconds;
    }

}

回答by Adam Winnipass

Made some few changes to Johnnyfittizio's answer. https://stackoverflow.com/a/40784539/4579897

对 Johnnyfittizio 的回答做了一些改动。https://stackoverflow.com/a/40784539/4579897

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 );
    }

}

回答by tommyc38

I thought it made more sense to create the timer as a Service so I can have more flexibility when creating my views (use the returned Time model however you want in your components). It creates a new observable upon subscription so each subscriber gets their own observable. In short, you can create as many timers at the same time with this service as you want. Be sure to include this service in your AppModule provider's array so you can use it throughout your application.

我认为将计时器创建为服务更有意义,这样我在创建视图时就可以有更大的灵活性(在组件中随意使用返回的时间模型)。它在订阅时创建一个新的 observable,因此每个订阅者都可以获得自己的 observable。简而言之,您可以根据需要使用此服务同时创建任意数量的计时器。请确保将此服务包含在您的 AppModule 提供程序的数组中,以便您可以在整个应用程序中使用它。

Service:

服务:

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))
  }
}

Now use it in a Component:

现在在组件中使用它:

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'))

  }

回答by Vinez

UPDATED for RXJS 5.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 );
  }

}

回答by Ryann Galea

Here's a solution i came up with recently on my project. It checks between a gate opening time of an event and the main event time of the same event. This uses Momentjs.

这是我最近在我的项目中提出的解决方案。它在一个事件的开门时间和同一事件的主要事件时间之间进行检查。这使用 Momentjs。

I have code in the onChanges function in case an event time changes in my firebase which is very unlikely, but i like the fact it can pick up on it and update on the fly.

我在 onChanges 函数中有代码,以防我的 firebase 中的事件时间发生变化,这是非常不可能的,但我喜欢它可以接收并动态更新的事实。

Component:

成分:

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:

HTML:

<span>{{countDown | async}}</span>

Produces: '2 Days 6 Hours 59 Mins 42' etc

制作:“2 天 6 小时 59 分 42”等