【问题标题】:Time CountDown in angular 2角度 2 倒计时时间
【发布时间】:2019-11-22 15:42:59
【问题描述】:

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

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

但在角度 2 中,我发现这个 plunkr 每 500 毫秒将一个数字加 1:

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。

【问题讨论】:

    标签: javascript angular


    【解决方案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>
    

    【讨论】:

    • 是的,它可以工作我如何从我尝试这样的类中发送 inputdate 变量,但我在脚本中得到一个空值。
    • 你不需要 attr。只需使用 [inputDate] 必须是解析为日期的字符串。我的回答回答了你原来的问题,请问你能把它标记为正确吗?
    • @kolli 这是一个工作 plunkr 我使用输入从父级plnkr.co/edit/9HZOKBZ3h2ZpQc5kgSfn?p=preview获取变量
    • @DiegoUnanue 附加的 plunker 不工作请更新它!
    • @PardeepJain 你在这里......更新到 Angular 2 最终版本。 plnkr.co/edit/SYwehoZvDciRnZkIygU5 让我知道它是否有效。
    【解决方案2】:

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

    【讨论】:

    【解决方案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){
            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;
        }
    
    }
    

    【讨论】:

    【解决方案4】:

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

    服务:

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

      【讨论】:

      • 这完美无瑕。 +1
      【解决方案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' 等等

      【讨论】:

      • 如何输入时间?当我运行这个时得到一个 NaN。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-04
      相关资源
      最近更新 更多