admin管理员组

文章数量:1314556

I am utilizing the following script from CodePen

// Create Countdown
var Countdown = {

    // Backbone-like structure
    $el: $('.countdown'),

    // Params
    countdown_interval: null,
    total_seconds     : 0,

    // Initialize the countdown  
    init: function() {

    // DOM
        this.$ = {
        hours  : this.$el.find('.bloc-time.hours .figure'),
        minutes: this.$el.find('.bloc-time.min .figure'),
        seconds: this.$el.find('.bloc-time.sec .figure')
    };

    // Init countdown values
    this.values = {
            hours  : this.$.hours.parent().attr('data-init-value'),
        minutes: this.$.minutes.parent().attr('data-init-value'),
        seconds: this.$.seconds.parent().attr('data-init-value'),
    };

    // Initialize total seconds
    this.total_seconds = this.values.hours * 60 * 60 + (this.values.minutes * 60) + this.values.seconds;

    // Animate countdown to the end 
    this.count();    
    },

    count: function() {

    var that    = this,
        $hour_1 = this.$.hours.eq(0),
        $hour_2 = this.$.hours.eq(1),
        $min_1  = this.$.minutes.eq(0),
        $min_2  = this.$.minutes.eq(1),
        $sec_1  = this.$.seconds.eq(0),
        $sec_2  = this.$.seconds.eq(1);

        this.countdown_interval = setInterval(function() {

        if(that.total_seconds > 0) {

            --that.values.seconds;              

            if(that.values.minutes >= 0 && that.values.seconds < 0) {

                that.values.seconds = 59;
                --that.values.minutes;
            }

            if(that.values.hours >= 0 && that.values.minutes < 0) {

                that.values.minutes = 59;
                --that.values.hours;
            }

            // Update DOM values
            // Hours
            that.checkHour(that.values.hours, $hour_1, $hour_2);

            // Minutes
            that.checkHour(that.values.minutes, $min_1, $min_2);

            // Seconds
            that.checkHour(that.values.seconds, $sec_1, $sec_2);

            --that.total_seconds;
        }
        else {
            clearInterval(that.countdown_interval);
        }
    }, 1000);    
    },

    animateFigure: function($el, value) {

        var that         = this,
                $top         = $el.find('.top'),
            $bottom      = $el.find('.bottom'),
            $back_top    = $el.find('.top-back'),
            $back_bottom = $el.find('.bottom-back');

    // Before we begin, change the back value
    $back_top.find('span').html(value);

    // Also change the back bottom value
    $back_bottom.find('span').html(value);

    // Then animate
    TweenMax.to($top, 0.8, {
        rotationX           : '-180deg',
        transformPerspective: 300,
            ease                : Quart.easeOut,
        onComplete          : function() {

            $top.html(value);

            $bottom.html(value);

            TweenMax.set($top, { rotationX: 0 });
        }
    });

    TweenMax.to($back_top, 0.8, { 
        rotationX           : 0,
        transformPerspective: 300,
            ease                : Quart.easeOut, 
        clearProps          : 'all' 
    });    
    },

    checkHour: function(value, $el_1, $el_2) {

    var val_1       = value.toString().charAt(0),
        val_2       = value.toString().charAt(1),
        fig_1_value = $el_1.find('.top').html(),
        fig_2_value = $el_2.find('.top').html();

    if(value >= 10) {

        // Animate only if the figure has changed
        if(fig_1_value !== val_1) this.animateFigure($el_1, val_1);
        if(fig_2_value !== val_2) this.animateFigure($el_2, val_2);
    }
    else {

        // If we are under 10, replace first figure with 0
        if(fig_1_value !== '0') this.animateFigure($el_1, 0);
        if(fig_2_value !== val_1) this.animateFigure($el_2, val_1);
    }    
    }
};

// Let's go !
Countdown.init();

I have been trying to figure out for several hours how to modify it to support multiple countdown timers per page.

My approach so far was to try adding a numeric counter so that each "countdown" element gets a unique class, and then modifying the script to run on each element but this did not work and I don't think it will.

I'm not sure how else to approach it though so would appreciate some input.

I am utilizing the following script from CodePen

// Create Countdown
var Countdown = {

    // Backbone-like structure
    $el: $('.countdown'),

    // Params
    countdown_interval: null,
    total_seconds     : 0,

    // Initialize the countdown  
    init: function() {

    // DOM
        this.$ = {
        hours  : this.$el.find('.bloc-time.hours .figure'),
        minutes: this.$el.find('.bloc-time.min .figure'),
        seconds: this.$el.find('.bloc-time.sec .figure')
    };

    // Init countdown values
    this.values = {
            hours  : this.$.hours.parent().attr('data-init-value'),
        minutes: this.$.minutes.parent().attr('data-init-value'),
        seconds: this.$.seconds.parent().attr('data-init-value'),
    };

    // Initialize total seconds
    this.total_seconds = this.values.hours * 60 * 60 + (this.values.minutes * 60) + this.values.seconds;

    // Animate countdown to the end 
    this.count();    
    },

    count: function() {

    var that    = this,
        $hour_1 = this.$.hours.eq(0),
        $hour_2 = this.$.hours.eq(1),
        $min_1  = this.$.minutes.eq(0),
        $min_2  = this.$.minutes.eq(1),
        $sec_1  = this.$.seconds.eq(0),
        $sec_2  = this.$.seconds.eq(1);

        this.countdown_interval = setInterval(function() {

        if(that.total_seconds > 0) {

            --that.values.seconds;              

            if(that.values.minutes >= 0 && that.values.seconds < 0) {

                that.values.seconds = 59;
                --that.values.minutes;
            }

            if(that.values.hours >= 0 && that.values.minutes < 0) {

                that.values.minutes = 59;
                --that.values.hours;
            }

            // Update DOM values
            // Hours
            that.checkHour(that.values.hours, $hour_1, $hour_2);

            // Minutes
            that.checkHour(that.values.minutes, $min_1, $min_2);

            // Seconds
            that.checkHour(that.values.seconds, $sec_1, $sec_2);

            --that.total_seconds;
        }
        else {
            clearInterval(that.countdown_interval);
        }
    }, 1000);    
    },

    animateFigure: function($el, value) {

        var that         = this,
                $top         = $el.find('.top'),
            $bottom      = $el.find('.bottom'),
            $back_top    = $el.find('.top-back'),
            $back_bottom = $el.find('.bottom-back');

    // Before we begin, change the back value
    $back_top.find('span').html(value);

    // Also change the back bottom value
    $back_bottom.find('span').html(value);

    // Then animate
    TweenMax.to($top, 0.8, {
        rotationX           : '-180deg',
        transformPerspective: 300,
            ease                : Quart.easeOut,
        onComplete          : function() {

            $top.html(value);

            $bottom.html(value);

            TweenMax.set($top, { rotationX: 0 });
        }
    });

    TweenMax.to($back_top, 0.8, { 
        rotationX           : 0,
        transformPerspective: 300,
            ease                : Quart.easeOut, 
        clearProps          : 'all' 
    });    
    },

    checkHour: function(value, $el_1, $el_2) {

    var val_1       = value.toString().charAt(0),
        val_2       = value.toString().charAt(1),
        fig_1_value = $el_1.find('.top').html(),
        fig_2_value = $el_2.find('.top').html();

    if(value >= 10) {

        // Animate only if the figure has changed
        if(fig_1_value !== val_1) this.animateFigure($el_1, val_1);
        if(fig_2_value !== val_2) this.animateFigure($el_2, val_2);
    }
    else {

        // If we are under 10, replace first figure with 0
        if(fig_1_value !== '0') this.animateFigure($el_1, 0);
        if(fig_2_value !== val_1) this.animateFigure($el_2, val_1);
    }    
    }
};

// Let's go !
Countdown.init();

I have been trying to figure out for several hours how to modify it to support multiple countdown timers per page.

My approach so far was to try adding a numeric counter so that each "countdown" element gets a unique class, and then modifying the script to run on each element but this did not work and I don't think it will.

I'm not sure how else to approach it though so would appreciate some input.

Share Improve this question edited Oct 25, 2019 at 22:43 Mister Jojo 22.4k6 gold badges25 silver badges42 bronze badges asked Oct 8, 2019 at 22:12 Zach NicodemousZach Nicodemous 9,4979 gold badges49 silver badges72 bronze badges 6
  • Create one Countdown for each timer? In other words, init a Countdown for every timer you need. If you know the number of timers beforehand, you can do it in a loop and add the Countdown objects to an array, for example. – devlin carnate Commented Oct 8, 2019 at 22:24
  • Its not always going to be a known amount of timers and I'd prefer to avoid having to duplicate the entire 'Countdown' code for every timer. Unless I misunderstood you. Can you show an example? – Zach Nicodemous Commented Oct 8, 2019 at 22:40
  • You don't have to repeat code. I believe you can wrap your Countdown in a function and then call that function multiple times based on an event/trigger. You will need to modify the "target" in HTML so that each object has it's own HMTL. And I believe one way to achieve that would be to clone a "template" HTML for each instance. – devlin carnate Commented Oct 8, 2019 at 23:30
  • I've tried implementing your solution without much luck thus far. Are you able to assist? – Zach Nicodemous Commented Oct 10, 2019 at 17:11
  • You can register each counter initial timestamp in global context and check if the new counter timestamp and is going to be matched with other counter current timestamp. If yes then change it by some certain value that should not conflict with other timestamp as well. – sagar Commented Oct 15, 2019 at 20:24
 |  Show 1 more ment

4 Answers 4

Reset to default 6 +50

You can create a new instance of this object with just a little bit of refactoring by converting it into a function.

For example, if you clone your <div class="countdown"/> HTML, and in JS you call:

new Countdown($($('.countdown')[0])).init();
new Countdown($($('.countdown')[1])).init();

Or, alternatively you could also initialize all .countdowns on page with:

$('.countdown').each((_, el) => (new Countdown($(el)).init()));

you will have two unique instances of the countdown.

// Create Countdown
function Countdown(node) {
  this.$el = node;
  this.countdown_interval = null;
  this.total_seconds = 0;
  this.init = function() {
    // DOM
    this.$ = {
      hours: this.$el.find('.bloc-time.hours .figure'),
      minutes: this.$el.find('.bloc-time.min .figure'),
      seconds: this.$el.find('.bloc-time.sec .figure')
    };

    // Init countdown values
    this.values = {
      hours: this.$.hours.parent().attr('data-init-value'),
      minutes: this.$.minutes.parent().attr('data-init-value'),
      seconds: this.$.seconds.parent().attr('data-init-value'),
    };

    // Initialize total seconds
    this.total_seconds = (this.values.hours * 60 * 60) +
      (this.values.minutes * 60) +
      this.values.seconds;
    // Animate countdown to the end 
    this.count();
  };
  this.count = function() {
    let that = this,
      $hour_1 = this.$.hours.eq(0),
      $hour_2 = this.$.hours.eq(1),
      $min_1 = this.$.minutes.eq(0),
      $min_2 = this.$.minutes.eq(1),
      $sec_1 = this.$.seconds.eq(0),
      $sec_2 = this.$.seconds.eq(1);

    this.countdown_interval = setInterval(function() {
      if (that.total_seconds > 0) {
        --that.values.seconds;
        if (that.values.minutes >= 0 && that.values.seconds < 0) {
          that.values.seconds = 59;
          --that.values.minutes;
        }

        if (that.values.hours >= 0 && that.values.minutes < 0) {
          that.values.minutes = 59;
          --that.values.hours;
        }

        // Update DOM values
        // Hours
        that.checkHour(that.values.hours, $hour_1, $hour_2);
        // Minutes
        that.checkHour(that.values.minutes, $min_1, $min_2);
        // Seconds
        that.checkHour(that.values.seconds, $sec_1, $sec_2);

        --that.total_seconds;
      } else {
        clearInterval(that.countdown_interval);
      }
    }, 1000);
  };
  this.animateFigure = function($el, value) {
    let that = this,
      $top = $el.find('.top'),
      $bottom = $el.find('.bottom'),
      $back_top = $el.find('.top-back'),
      $back_bottom = $el.find('.bottom-back');

    // Before we begin, change the back value
    $back_top.find('span').html(value);

    // Also change the back bottom value
    $back_bottom.find('span').html(value);

    // Then animate
    TweenMax.to($top, 0.8, {
      rotationX: '-180deg',
      transformPerspective: 300,
      ease: Quart.easeOut,
      onComplete: function() {
        $top.html(value);
        $bottom.html(value);
        TweenMax.set($top, {
          rotationX: 0
        });
      }
    });

    TweenMax.to($back_top, 0.8, {
      rotationX: 0,
      transformPerspective: 300,
      ease: Quart.easeOut,
      clearProps: 'all'
    });
  };
  this.checkHour = function(value, $el_1, $el_2) {
    let val_1 = value.toString().charAt(0),
      val_2 = value.toString().charAt(1),
      fig_1_value = $el_1.find('.top').html(),
      fig_2_value = $el_2.find('.top').html();

    if (value >= 10) {
      // Animate only if the figure has changed
      if (fig_1_value !== val_1) this.animateFigure($el_1, val_1);
      if (fig_2_value !== val_2) this.animateFigure($el_2, val_2);
    } else {
      // If we are under 10, replace first figure with 0
      if (fig_1_value !== '0') this.animateFigure($el_1, 0);
      if (fig_2_value !== val_1) this.animateFigure($el_2, val_1);
    }
  }
}

// Let's go !
new Countdown($($('.countdown')[0])).init();
new Countdown($($('.countdown')[1])).init();

// Alternatively you could also initialize all countdowns on page with:
// $('.countdown').each((i, el) => (new Countdown($(el)).init()));
body {
  background-color: #f2f1ed;
}

.wrap {
  position: absolute;
  bottom: 0;
  top: 0;
  left: 0;
  right: 0;
  margin: auto;
  height: 310px;
}

a {
  text-decoration: none;
  color: #1a1a1a;
}

h1 {
  margin-bottom: 60px;
  text-align: center;
  font: 300 2.25em "Lato";
  text-transform: uppercase;
}

h1 strong {
  font-weight: 400;
  color: #ea4c4c;
}

h2 {
  margin-bottom: 80px;
  text-align: center;
  font: 300 0.7em "Lato";
  text-transform: uppercase;
}

h2 strong {
  font-weight: 400;
}

.countdown {
  width: 720px;
  margin: 4px 0;
  display: inline-block;
}

.countdown .bloc-time {
  float: left;
  margin-right: 45px;
  text-align: center;
}

.countdown .bloc-time:last-child {
  margin-right: 0;
}

.countdown .count-title {
  display: block;
  margin-bottom: 15px;
  font: normal 0.94em "Lato";
  color: #1a1a1a;
  text-transform: uppercase;
}

.countdown .figure {
  position: relative;
  float: left;
  height: 110px;
  width: 100px;
  margin-right: 10px;
  background-color: #fff;
  border-radius: 8px;
  -moz-box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.2), inset 2px 4px 0 0 rgba(255, 255, 255, 0.08);
  -webkit-box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.2), inset 2px 4px 0 0 rgba(255, 255, 255, 0.08);
  box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.2), inset 2px 4px 0 0 rgba(255, 255, 255, 0.08);
}

.countdown .figure:last-child {
  margin-right: 0;
}

.countdown .figure>span {
  position: absolute;
  left: 0;
  right: 0;
  margin: auto;
  font: normal 5.94em/107px "Lato";
  font-weight: 700;
  color: #de4848;
}

.countdown .figure .top:after,
.countdown .figure .bottom-back:after {
  content: "";
  position: absolute;
  z-index: -1;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}

.countdown .figure .top {
  z-index: 3;
  background-color: #f7f7f7;
  transform-origin: 50% 100%;
  -webkit-transform-origin: 50% 100%;
  -moz-border-radius-topleft: 10px;
  -webkit-border-top-left-radius: 10px;
  border-top-left-radius: 10px;
  -moz-border-radius-topright: 10px;
  -webkit-border-top-right-radius: 10px;
  border-top-right-radius: 10px;
  -moz-transform: perspective(200px);
  -ms-transform: perspective(200px);
  -webkit-transform: perspective(200px);
  transform: perspective(200px);
}

.countdown .figure .bottom {
  z-index: 1;
}

.countdown .figure .bottom:before {
  content: "";
  position: absolute;
  display: block;
  top: 0;
  left: 0;
  width: 100%;
  height: 50%;
  background-color: rgba(0, 0, 0, 0.02);
}

.countdown .figure .bottom-back {
  z-index: 2;
  top: 0;
  height: 50%;
  overflow: hidden;
  background-color: #f7f7f7;
  -moz-border-radius-topleft: 10px;
  -webkit-border-top-left-radius: 10px;
  border-top-left-radius: 10px;
  -moz-border-radius-topright: 10px;
  -webkit-border-top-right-radius: 10px;
  border-top-right-radius: 10px;
}

.countdown .figure .bottom-back span {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  margin: auto;
}

.countdown .figure .top,
.countdown .figure .top-back {
  height: 50%;
  overflow: hidden;
  -moz-backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

.countdown .figure .top-back {
  z-index: 4;
  bottom: 0;
  background-color: #fff;
  -webkit-transform-origin: 50% 0;
  transform-origin: 50% 0;
  -moz-transform: perspective(200px) rotateX(180deg);
  -ms-transform: perspective(200px) rotateX(180deg);
  -webkit-transform: perspective(200px) rotateX(180deg);
  transform: perspective(200px) rotateX(180deg);
  -moz-border-radius-bottomleft: 10px;
  -webkit-border-bottom-left-radius: 10px;
  border-bottom-left-radius: 10px;
  -moz-border-radius-bottomright: 10px;
  -webkit-border-bottom-right-radius: 10px;
  border-bottom-right-radius: 10px;
}

.countdown .figure .top-back span {
  position: absolute;
  top: -100%;
  left: 0;
  right: 0;
  margin: auto;
}
<script src="https://cdnjs.cloudflare./ajax/libs/gsap/latest/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
  <h1>Draft <strong>Countdown</strong></h1>

  <!-- Countdown #1 -->
  <div class="countdown">
    <div class="bloc-time hours" data-init-value="24">
      <span class="count-title">Hours</span>

      <div class="figure hours hours-1">
        <span class="top">2</span>
        <span class="top-back">
          <span>2</span>
        </span>
        <span class="bottom">2</span>
        <span class="bottom-back">
          <span>2</span>
        </span>
      </div>

      <div class="figure hours hours-2">
        <span class="top">4</span>
        <span class="top-back">
          <span>4</span>
        </span>
        <span class="bottom">4</span>
        <span class="bottom-back">
          <span>4</span>
        </span>
      </div>
    </div>

    <div class="bloc-time min" data-init-value="0">
      <span class="count-title">Minutes</span>

      <div class="figure min min-1">
        <span class="top">0</span>
        <span class="top-back">
          <span>0</span>
        </span>
        <span class="bottom">0</span>
        <span class="bottom-back">
          <span>0</span>
        </span>
      </div>

      <div class="figure min min-2">
        <span class="top">0</span>
        <span class="top-back">
          <span>0</span>
        </span>
        <span class="bottom">0</span>
        <span class="bottom-back">
          <span>0</span>
        </span>
      </div>
    </div>

    <div class="bloc-time sec" data-init-value="0">
      <span class="count-title">Seconds</span>

      <div class="figure sec sec-1">
        <span class="top">0</span>
        <span class="top-back">
          <span>0</span>
        </span>
        <span class="bottom">0</span>
        <span class="bottom-back">
          <span>0</span>
        </span>
      </div>

      <div class="figure sec sec-2">
        <span class="top">0</span>
        <span class="top-back">
          <span>0</span>
        </span>
        <span class="bottom">0</span>
        <span class="bottom-back">
          <span>0</span>
        </span>
      </div>
    </div>
  </div>

  <div class="countdown">
    <div class="bloc-time hours" data-init-value="4">
      <span class="count-title">Hours</span>

      <div class="figure hours hours-1">
        <span class="top">0</span>
        <span class="top-back">
          <span>0</span>
        </span>
        <span class="bottom">0</span>
        <span class="bottom-back">
          <span>0</span>
        </span>
      </div>

      <div class="figure hours hours-2">
        <span class="top">4</span>
        <span class="top-back">
          <span>4</span>
        </span>
        <span class="bottom">4</span>
        <span class="bottom-back">
          <span>4</span>
        </span>
      </div>
    </div>

    <div class="bloc-time min" data-init-value="30">
      <span class="count-title">Minutes</span>

      <div class="figure min min-1">
        <span class="top">3</span>
        <span class="top-back">
          <span>3</span>
        </span>
        <span class="bottom">3</span>
        <span class="bottom-back">
          <span>3</span>
        </span>
      </div>

      <div class="figure min min-2">
        <span class="top">0</span>
        <span class="top-back">
          <span>0</span>
        </span>
        <span class="bottom">0</span>
        <span class="bottom-back">
          <span>0</span>
        </span>
      </div>
    </div>

    <div class="bloc-time sec" data-init-value="30">
      <span class="count-title">Seconds</span>

      <div class="figure sec sec-1">
        <span class="top">3</span>
        <span class="top-back">
          <span>3</span>
        </span>
        <span class="bottom">3</span>
        <span class="bottom-back">
          <span>3</span>
        </span>
      </div>

      <div class="figure sec sec-2">
        <span class="top">0</span>
        <span class="top-back">
          <span>0</span>
        </span>
        <span class="bottom">0</span>
        <span class="bottom-back">
          <span>0</span>
        </span>
      </div>
    </div>
  </div>
</div>

Here's a link to the updated codepen.

Hope this helps,

As a jQuery plugin it could go this way (you can customize it further):

// Create Countdown Plugin
$.fn.fancyCountdown = function() {
 
    return this.each(function() {
        
		var that=this;
		var $el=$(this);
		
		that.values = {
			titleHours: 'Hours',
			titleMinutes: 'Minutes',
			titleSeconds: 'Seconds'
		};
		
		if( $el.data('settings') ) {
			that.values = $el.data('settings');
		} else {
			that.values = $.extend( {}, that.values, $el.data() );
		};
		var explodeTime = that.values.time.split(':');
		that.values.hours = explodeTime[0]*1;
		that.values.minutes = explodeTime[1]*1;
		that.values.seconds = explodeTime[2]*1;
		that.values.hours1 = explodeTime[0][0];
		that.values.hours2 = explodeTime[0][1];
		that.values.minutes1 = explodeTime[1][0];
		that.values.minutes2 = explodeTime[1][1];
		that.values.seconds1 = explodeTime[2][0];
		that.values.seconds2 = explodeTime[2][1];
		that.values.totalSeconds = that.values.hours*60*60 + that.values.minutes*60 + that.values.seconds;
		that.values.template = '\
			<span class="top">#</span>\
			<span class="top-back">\
				<span>#</span>\
			</span>\
			<span class="bottom">#</span>\
			<span class="bottom-back">\
				<span>#</span>\
			</span>\
		';
		that.countdownInterval = null;
		
		if( !$el.hasClass('countdown-engaged') ) {
		
			$el.addClass('countdown-engaged');

			// Initialize the countdown  
			that.init=function() {

				// DOM
				that.createDom();
				that.$ = {
					hours: $el.find('.bloc-time.hours .figure'),
					minutes: $el.find('.bloc-time.min .figure'),
					seconds: $el.find('.bloc-time.sec .figure')
				};

				// Animate countdown to the end 
				that.count();
			};
			
			that.createDom = function() {
				var html = '\
					<div class="bloc-time hours">\
						<span class="count-title">' + that.values.titleHours + '</span>\
						<div class="figure hours hours-1">\
							' + that.values.template.replace(/#/g, that.values.hours1) + '\
						</div>\
						<div class="figure hours hours-2">\
							' + that.values.template.replace(/#/g, that.values.hours2) + '\
						</div>\
					</div>\
					<div class="bloc-time min">\
						<span class="count-title">' + that.values.titleMinutes + '</span>\
						<div class="figure min min-1">\
							' + that.values.template.replace(/#/g, that.values.minutes1) + '\
						</div>\
						<div class="figure min min-2">\
							' + that.values.template.replace(/#/g, that.values.minutes2) + '\
						</div>\
					</div>\
					<div class="bloc-time sec">\
						<span class="count-title">' + that.values.titleSeconds + '</span>\
						<div class="figure sec sec-1">\
							' + that.values.template.replace(/#/g, that.values.seconds1) + '\
						</div>\
						<div class="figure sec sec-2">\
							' + that.values.template.replace(/#/g, that.values.seconds2) + '\
						</div>\
					</div>\
				';
				$el.html(html);
			};

			that.count = function() {
				var $hour_1 = that.$.hours.eq(0),
					$hour_2 = that.$.hours.eq(1),
					$min_1 = that.$.minutes.eq(0),
					$min_2 = that.$.minutes.eq(1),
					$sec_1 = that.$.seconds.eq(0),
					$sec_2 = that.$.seconds.eq(1);

				that.countdownInterval = setInterval(function() {

					if (that.values.totalSeconds > 0) {

						--that.values.seconds;

						if (that.values.minutes >= 0 && that.values.seconds < 0) {
							that.values.seconds = 59;
							--that.values.minutes;
						}

						if (that.values.hours >= 0 && that.values.minutes < 0) {
							that.values.minutes = 59;
							--that.values.hours;
						}

						// Update DOM values
						// Hours
						that.checkHour(that.values.hours, $hour_1, $hour_2);

						// Minutes
						that.checkHour(that.values.minutes, $min_1, $min_2);

						// Seconds
						that.checkHour(that.values.seconds, $sec_1, $sec_2);

						--that.values.totalSeconds;
					} else {
						clearInterval(that.countdownInterval);
					};
				}, 1000);
			};

			that.animateFigure = function($el, value) {

				var $top = $el.find('.top'),
					$bottom = $el.find('.bottom'),
					$back_top = $el.find('.top-back'),
					$back_bottom = $el.find('.bottom-back');

				// Before we begin, change the back value
				$back_top.find('span').html(value);

				// Also change the back bottom value
				$back_bottom.find('span').html(value);

				// Then animate
				TweenMax.to($top, 0.8, {
					rotationX: '-180deg',
					transformPerspective: 300,
					ease: Quart.easeOut,
					onComplete: function() {

						$top.html(value);

						$bottom.html(value);

						TweenMax.set($top, {
							rotationX: 0
						});
					}
				});

				TweenMax.to($back_top, 0.8, {
					rotationX: 0,
					transformPerspective: 300,
					ease: Quart.easeOut,
					clearProps: 'all'
				});
			};

			that.checkHour=function(value, $el_1, $el_2) {

				var val_1 = value.toString().charAt(0),
					val_2 = value.toString().charAt(1),
					fig_1_value = $el_1.find('.top').html(),
					fig_2_value = $el_2.find('.top').html();

				if (value >= 10) {

					// Animate only if the figure has changed
					if (fig_1_value !== val_1) that.animateFigure($el_1, val_1);
					if (fig_2_value !== val_2) that.animateFigure($el_2, val_2);
				} else {

					// If we are under 10, replace first figure with 0
					if (fig_1_value !== '0') that.animateFigure($el_1, 0);
					if (fig_2_value !== val_1) that.animateFigure($el_2, val_1);
				}
			};
			
		};
		
		that.init();
		
    });
 
};

$('.countdown').fancyCountdown();
body {
    background-color: #f2f1ed;
}

.wrap {
    margin: 0 auto;
    height: 310px;
}

a {
    text-decoration: none;
    color: #1a1a1a;
}

h1 {
    margin-bottom: 60px;
    text-align: center;
    font: 300 2.25em "Lato";
    text-transform: uppercase;
}

h1 strong {
    font-weight: 400;
    color: #ea4c4c;
}

h2 {
    margin-bottom: 80px;
    text-align: center;
    font: 300 0.7em "Lato";
    text-transform: uppercase;
}

h2 strong {
    font-weight: 400;
}

.countdown {
    width: 720px;
    margin: 0 auto;
}

.countdown .bloc-time {
    float: left;
    margin-right: 45px;
    text-align: center;
}

.countdown .bloc-time:last-child {
    margin-right: 0;
}

.countdown .count-title {
    display: block;
    margin-bottom: 15px;
    font: normal 0.94em "Lato";
    color: #1a1a1a;
    text-transform: uppercase;
}

.countdown .figure {
    position: relative;
    float: left;
    height: 110px;
    width: 100px;
    margin-right: 10px;
    background-color: #fff;
    border-radius: 8px;
    -moz-box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.2), inset 2px 4px 0 0 rgba(255, 255, 255, 0.08);
    -webkit-box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.2), inset 2px 4px 0 0 rgba(255, 255, 255, 0.08);
    box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.2), inset 2px 4px 0 0 rgba(255, 255, 255, 0.08);
}

.countdown .figure:last-child {
    margin-right: 0;
}

.countdown .figure>span {
    position: absolute;
    left: 0;
    right: 0;
    margin: auto;
    font: normal 5.94em/107px "Lato";
    font-weight: 700;
    color: #de4848;
}

.countdown .figure .top:after,
.countdown .figure .bottom-back:after {
    content: "";
    position: absolute;
    z-index: -1;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 100%;
    border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}

.countdown .figure .top {
    z-index: 3;
    background-color: #f7f7f7;
    transform-origin: 50% 100%;
    -webkit-transform-origin: 50% 100%;
    -moz-border-radius-topleft: 10px;
    -webkit-border-top-left-radius: 10px;
    border-top-left-radius: 10px;
    -moz-border-radius-topright: 10px;
    -webkit-border-top-right-radius: 10px;
    border-top-right-radius: 10px;
    -moz-transform: perspective(200px);
    -ms-transform: perspective(200px);
    -webkit-transform: perspective(200px);
    transform: perspective(200px);
}

.countdown .figure .bottom {
    z-index: 1;
}

.countdown .figure .bottom:before {
    content: "";
    position: absolute;
    display: block;
    top: 0;
    left: 0;
    width: 100%;
    height: 50%;
    background-color: rgba(0, 0, 0, 0.02);
}

.countdown .figure .bottom-back {
    z-index: 2;
    top: 0;
    height: 50%;
    overflow: hidden;
    background-color: #f7f7f7;
    -moz-border-radius-topleft: 10px;
    -webkit-border-top-left-radius: 10px;
    border-top-left-radius: 10px;
    -moz-border-radius-topright: 10px;
    -webkit-border-top-right-radius: 10px;
    border-top-right-radius: 10px;
}

.countdown .figure .bottom-back span {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    margin: auto;
}

.countdown .figure .top,
.countdown .figure .top-back {
    height: 50%;
    overflow: hidden;
    -moz-backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}

.countdown .figure .top-back {
    z-index: 4;
    bottom: 0;
    background-color: #fff;
    -webkit-transform-origin: 50% 0;
    transform-origin: 50% 0;
    -moz-transform: perspective(200px) rotateX(180deg);
    -ms-transform: perspective(200px) rotateX(180deg);
    -webkit-transform: perspective(200px) rotateX(180deg);
    transform: perspective(200px) rotateX(180deg);
    -moz-border-radius-bottomleft: 10px;
    -webkit-border-bottom-left-radius: 10px;
    border-bottom-left-radius: 10px;
    -moz-border-radius-bottomright: 10px;
    -webkit-border-bottom-right-radius: 10px;
    border-bottom-right-radius: 10px;
}

.countdown .figure .top-back span {
    position: absolute;
    top: -100%;
    left: 0;
    right: 0;
    margin: auto;
}
<script src="https://cdnjs.cloudflare./ajax/libs/gsap/latest/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
    <h1>Draft <strong>Countdown</strong></h1>
    <div class="countdown" data-time="22:30:00"></div>
</div>
<div class="wrap">
	<h1>Second <strong>Countdown</strong></h1>
    <div class="countdown" data-settings='{"time": "01:22:50", "titleHours": "Sati", "titleMinutes": "Minuti", "titleSeconds": "Sekunde"}'></div>
</div>

Also on JSFiddle.

I only kept the visual aspect in CSS (with some modifications) and I pletely rewrote all the code in "pure" Javascript (no jQuery) and keeping the GSAP / TweenMax library.

You can put as many countDown as you want by filling in an array indicating the titles and durations etc.

There is only one setInterval handling the different countDown and it will stop with the last active countDown.

I chose this solution because using several setInterval at the same time seemed to me disproportionate for that, and unnecessarily overload the OS.

For greater accuracy, all countDowns are based on the system clock (and not on the call cycles of the setInterval, because they are "naturally" shifted and are therefore inpatible for any use of time measurement).

This script makes it possible to carry out 2 types of countDown:
- for a fixed duration (eg 6 minutes for eggs)
- either on a date (or time) end (ex: birthday, appointment ...)

The other interest of this script is that it generates on demand the set of elements html useful to the display of countDown on the page, and it allows to choose the display with the number of desired units

const myCountDowns= [ { title: 'timer <strong>24h</strong>'
                      , type : 'Hours'
                      , timer: '24h'
                      } 
                    , { title: 'Tea cup <strong>2\' 45"</strong>'
                      , type : 'Minutes'
                      , timer: '2m 45s'
                      } 
                    , { title: 'until the new year <strong>2020</strong>'
                      , type : 'Days'
                      , date : '01 01 2020' // local Month Day Year
                      } 
                    ] 

CountDown.BuildsAndRun( myCountDowns )

// ->type : 'Days'  or 'Hours' or 'Minutes' or 'seconds'
// set "timer" for time duration  otherwise set a "date" value

// timer string format is _number_UNIT where UNIT = 'd','h','m','s'  for Days, Hours, Minutes, Seconds
// ex : '3d 25m 6s'  = 3 days 0 hours 25 minutes, 6 seconds  (days = 0, 0 is defauls for all units)
// ex : '6s 3d 25m'  = the same, there is no order
// date format is JS Date format  see new Date( _STRING_ )

FULL CODE (on snippet below)

(function( CountDown )
  {
  // Private vars
  const domEndBody     = document.body.querySelector('script') || document.body // for countDowns insert place
      , eWrapp         = document.createElement('div')
      , eTitle         = document.createElement('h1')
      , eCountDown     = document.createElement('div')
      , eTimeBlock     = document.createElement('div')
      , eCountTitle    = document.createElement('span')
      , eFigure        = document.createElement('div')
      , counters       = []                              // list of CountDowns
      , one_Sec        = 1000
      , one_Min        = one_Sec * 60
      , one_Hour       = one_Min * 60 
      , one_Day        = one_Hour * 24
      , padZ =(val,sz) => ('0'.repeat(sz)+val.toString(10)).slice(-sz) // return string with leading zeros
      , Interface      = [ { xL:8, Title:'Days',    Fig:3 }            // titles & counts of figures
                         , { xL:5, Title:'Hours',   Fig:2 } 
                         , { xL:3, Title:'Minutes', Fig:2 } 
                         , { xL:0, Title:'Seconds', Fig:2 } 
                         ]
      , animOpt        = { rotationX: 0, transformPerspective: 300, ease: Quart.easeOut, clearProps: 'all' }

  var activeCounters   = 0

  // finalize countDown elements
  eWrapp.className      = 'wrap'
  eTitle.innerHTML      = 'F<strong>D</strong>'  // 'Draft <strong>Countdown</strong>'
  eCountDown.className  = 'countdown'
  eTimeBlock.className  = 'bloc-time'
  eCountTitle.className = 'count-title'
  eFigure.className     = 'figure'
  eFigure.innerHTML     = '<span class="top"        > </span>'
                        + ' <span class="top-back"   > <span> </span> </span>'
                        + ' <span class="bottom"     > </span>'
                        + ' <span class="bottom-back"> <span> </span> </span>'

  //Public Method ........................................................................
  CountDown.BuildsAndRun = function( TimerArray )
    {
    for (let TimerParms of TimerArray) 
      { CountDown_Build ( TimerParms ) }

    setTimeout(() => { CountDown_Run() }, 300);  // the Timeout is just for start spectacle
    }                 

  // Private Methods......................................................................
  CountDown_Build = function( parms )
    {
    let len = parms.type==='Hours'?6:parms.type==='Minutes'?4:parms.type==='seconds'?2:9
      , ctD = { lg     : len              // countDown number of figure (digits)
              , face   : ' '.repeat(len)  // actuel face of countDown
              , fig    : []               // array of firures (DOM elements)
              , ref    : counters.length  // ID  of this countDown
              , time   : null             // time to add to pute taget time for CountDown
              , target : null             // target Timie value
              , activ  : true             // to check if count down is activ or not ( finished )
              }
    // generate all Figures of CountDown          
    for(let i=len;i--;) {                     // from len to 0 (just my fav ninja)
      ctD.fig.push( eFigure.cloneNode(true) )
      }
    // CountDown DOM making
    let xWrapp     = eWrapp.cloneNode(true)
      , xTitle     = eTitle.cloneNode(true)
      , xCountDown = eCountDown.cloneNode(true)
      , noFig      = 0                          // ref on the first ctD.fig list (of figures)

    xTitle.innerHTML       = parms.title
    xWrapp.style.width = len===9?'1105px':len===6?'740px':len===4?'485px':'230px'
    //xCountDown.style.width = len===9?'1090px':len===6?'730px':len===4?'470px':'230px'

    xWrapp.appendChild(xTitle)
    xWrapp.appendChild(xCountDown)

    // making of bloc-time elements
    for(eBlk of Interface)
      {
      if(len>eBlk.xL)
        {
        let xTimeBlock  = eTimeBlock.cloneNode(true)
          , xCountTitle = eCountTitle.cloneNode(true)

        xCountTitle.textContent = eBlk.Title
        xTimeBlock.appendChild(xCountTitle)
        for(let f=eBlk.Fig;f--;)                        // (fav ninja again)
          { xTimeBlock.appendChild(ctD.fig[noFig++]) } // move figures inside
        xCountDown.appendChild(xTimeBlock)
        }
      }
    document.body.insertBefore(xWrapp, domEndBody)   // insert CountDowm on page

    // set count down initial values 
    if (parms.timer)   // in case of timer...
      {
      let TimeInfos = get_DHMS(parms.timer, len )
      ctD.time      = TimeInfos.add 
      counters.push( ctD )
      activeCounters++
      updateInterface( ctD.ref, TimeInfos.dis )  // show first figure faces
      }
    else if (parms.date) // in case of CountDown until date
      {
      ctD.target = new Date(parms.date);
      counters.push( ctD ) 
      if (showFaceOnNow( ctD.ref ))
        { activeCounters++ }
      }
    }
  CountDown_Run = function()
    {
    for (let elm of counters)
      { 
      if (elm.time)
        { elm.target = new Date().getTime() + elm.time }
      }
    let timerInterval = setInterval(_=>
      {
      counters.forEach((elm,ref)=>
        { 
        if ( elm.activ )
          {
          if (!showFaceOnNow( ref ))
            { activeCounters-- }
          }
        if ( activeCounters<=0 )
          { clearInterval(timerInterval) }  
        })
      }
      , one_Sec )
    }  
  showFaceOnNow = function(ref)
    {
    let now = new Date().getTime()
    , tim   = counters[ref].target - now
    , face  = '0'.repeat( counters[ref].lg )
    
    if (tim >= 0)
      {
      face  = padZ(Math.floor(tim / one_Day), 3)
      face += padZ((Math.floor((tim % one_Day ) / one_Hour)), 2)
      face += padZ((Math.floor((tim % one_Hour) / one_Min )), 2)
      face += padZ((Math.floor((tim % one_Min ) / one_Sec )), 2)
      face = padZ( face, counters[ref].lg )
      }
    else
      {
      counters[ref].activ = false
      }
    updateInterface ( ref, face)
    return counters[ref].activ
    }
  updateInterface = function(ref, newVal)
    {
    for(let p = counters[ref].lg ; p--;)  // update faces figures backward
      {
      if (counters[ref].face.charAt(p) !== newVal.charAt(p))
        {
        animateFigure( counters[ref].fig[p], newVal.charAt(p) )
        }
      }
    counters[ref].face = newVal
    }
  get_DHMS = function (timer_val, lg)
    {
    let vDelay = { d:0, h:0, m:0, s:0 }
      , vNum   = '0'
      , ret    = { add: 0, dis: ''}
    for (const c of timer_val)
      {
      if (/[0-9]/.test(c) )  vNum += c
      if (/[dhms]/.test(c) )
        {
        vDelay[c] = parseInt(vNum)
        vNum      = '0'
        }
      }
    ret.add = (vDelay.d*one_Day)+(vDelay.h*one_Hour)+(vDelay.m*one_Min)+(vDelay.s*one_Sec)
    ret.dis = (padZ(vDelay.d,3)+padZ(vDelay.h,2)+padZ(vDelay.m,2)+padZ(vDelay.s,2)).slice(-lg)
    return ret
    }
  animateFigure = function (domElm, newChar) 
    {
    let eTop         = domElm.querySelector('.top')
      , eBottom      = domElm.querySelector('.bottom')
      , eBack_top    = domElm.querySelector('.top-back')

    // Before we begin, change the back value and the back bottom value
    eBack_top.querySelector('span').textContent           = newChar
    domElm.querySelector('.bottom-back span').textContent = newChar
    
    TweenMax.to(eTop, 0.8,          // Then animate
      { rotationX           : '-180deg'
      , transformPerspective: 300
      , ease                : Quart.easeOut
      , onComplete          : function()
        {
        eTop.textContent    = newChar
        eBottom.textContent = newChar
        TweenMax.set(eTop, { rotationX: 0 })
        }
      })
    TweenMax.to(eBack_top, 0.8, animOpt)
    }
  }( window.CountDown = window.CountDown || {}));


/********************************************************************************************/


const myCountDowns= [ { title: 'timer <strong>24h</strong>'
                      , type : 'Hours'
                      , timer: '24h'
                      } 
                    , { title: 'Tea cup <strong>2\' 45"</strong>'
                      , type : 'Minutes'
                      , timer: '2m 45s'
                      } 
                    , { title: 'until the new year <strong>2020</strong>'
                      , type : 'Days'
                      , date : '01 01 2020' // local Month Day Year
                      } 
                    ] 

CountDown.BuildsAndRun( myCountDowns )


// ->type : 'Days'  or 'Hours' or 'Minutes' or 'seconds'
// set "timer" for time duration  otherwise set a "date" value

// timer string format is _number_UNIT where UNIT = 'd','h','m','s'  for Days, Hours, Minutes, Seconds
// ex : '3d 25m 6s'  = 3 days 0 hours 25 minutes, 6 seconds  (days = 0, 0 is defauls for all units)
// ex : '6s 3d 25m'  = the same, there is no order
// date format is JS Date format  see new Date( _STRING_ )
body {
  background-color: #f2f1ed;
  margin: 0;
}
.wrap {
  margin: 2em auto;
  height: 270px;
  width: 1500px; /*   be re-calculate on JS */
  border-radius: 1em;
  padding: 10px 5px 0 5px;
  box-shadow: 0px 0px 1px 1px rgba(170, 170, 170, 0.64);
}
a {
  text-decoration: none;
  color: #1a1a1a;
}
h1 {
  margin-bottom: 30px;
  text-align: center;
  font: 300 2.25em "Lato";
  text-transform: uppercase;
}
h1 strong {
  font-weight: 400;
  color: #ea4c4c;
}
h2 {
  margin-bottom: 80px;
  text-align: center;
  font: 300 0.7em "Lato";
  text-transform: uppercase;
}
h2 strong {
  font-weight: 400;
}

.countdown {
/*   width: 100%;  or be re-calculate on JS */
  margin: 0 auto;
  padding: 0 10px 10px 10px;
}
.countdown .bloc-time {
  float: left;
  margin-right: 45px;
  text-align: center;
}
.countdown .bloc-time:last-child {
  margin-right: 0;
}
.countdown .count-title {
  display: block;
  margin-bottom: 15px;
  font: normal 0.94em "Lato";
  color: #1a1a1a;
  text-transform: uppercase;
}
.countdown .figure {
  position: relative;
  float: left;
  height: 110px;
  width: 100px;
  margin-right: 10px;
  background-color: #fff;
  border-radius: 8px;
  -moz-box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.2), inset 2px 4px 0 0 rgba(255, 255, 255, 0.08);
  -webkit-box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.2), inset 2px 4px 0 0 rgba(255, 255, 255, 0.08);
  box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.2), inset 2px 4px 0 0 rgba(255, 255, 255, 0.08);
}
.countdown .figure:last-child {
  margin-right: 0;
}
.countdown .figure > span {
  position: absolute;
  left: 0;
  right: 0;
  margin: auto;
  font: normal 5.94em/107px "Lato";
  font-weight: 700;
  color: #de4848;
}
.countdown .figure .top:after, .countdown .figure .bottom-back:after {
  content: "";
  position: absolute;
  z-index: -1;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.countdown .figure .top {
  z-index: 3;
  background-color: #f7f7f7;
  transform-origin: 50% 100%;
  -webkit-transform-origin: 50% 100%;
  -moz-border-radius-topleft: 10px;
  -webkit-border-top-left-radius: 10px;
  border-top-left-radius: 10px;
  -moz-border-radius-topright: 10px;
  -webkit-border-top-right-radius: 10px;
  border-top-right-radius: 10px;
  -moz-transform: perspective(200px);
  -ms-transform: perspective(200px);
  -webkit-transform: perspective(200px);
  transform: perspective(200px);
}
.countdown .figure .bottom {
  z-index: 1;
}
.countdown .figure .bottom:before {
  content: "";
  position: absolute;
  display: block;
  top: 0;
  left: 0;
  width: 100%;
  height: 50%;
  background-color: rgba(0, 0, 0, 0.02);
}
.countdown .figure .bottom-back {
  z-index: 2;
  top: 0;
  height: 50%;
  overflow: hidden;
  background-color: #f7f7f7;
  -moz-border-radius-topleft: 10px;
  -webkit-border-top-left-radius: 10px;
  border-top-left-radius: 10px;
  -moz-border-radius-topright: 10px;
  -webkit-border-top-right-radius: 10px;
  border-top-right-radius: 10px;
}
.countdown .figure .bottom-back span {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  margin: auto;
}
.countdown .figure .top, .countdown .figure .top-back {
  height: 50%;
  overflow: hidden;
  -moz-backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
.countdown .figure .top-back {
  z-index: 4;
  bottom: 0;
  background-color: #fff;
  -webkit-transform-origin: 50% 0;
  transform-origin: 50% 0;
  -moz-transform: perspective(200px) rotateX(180deg);
  -ms-transform: perspective(200px) rotateX(180deg);
  -webkit-transform: perspective(200px) rotateX(180deg);
  transform: perspective(200px) rotateX(180deg);
  -moz-border-radius-bottomleft: 10px;
  -webkit-border-bottom-left-radius: 10px;
  border-bottom-left-radius: 10px;
  -moz-border-radius-bottomright: 10px;
  -webkit-border-bottom-right-radius: 10px;
  border-bottom-right-radius: 10px;
}
.countdown .figure .top-back span {
  position: absolute;
  top: -100%;
  left: 0;
  right: 0;
  margin: auto;
}
<link href='https://fonts.googleapis./css?family=Lato:300,400,700' rel='stylesheet' type='text/css'>
<script src="https://cdnjs.cloudflare./ajax/libs/gsap/latest/TweenMax.min.js"></script>

<!-- no more HTML code -->

// Create Countdown
var Countdown = {

  // Backbone-like structure
  $el: $('.countdown'),

  // Params
  countdown_interval: null,
  total_seconds     : 0,

  // Initialize the countdown  
  init: function() {

    // DOM
        this.$ = {
        hours  : this.$el.find('.bloc-time.hours .figure'),
        minutes: this.$el.find('.bloc-time.min .figure'),
        seconds: this.$el.find('.bloc-time.sec .figure')
    };

    // Init countdown values
    this.values = {
          hours  : this.$.hours.parent().attr('data-init-value'),
        minutes: this.$.minutes.parent().attr('data-init-value'),
        seconds: this.$.seconds.parent().attr('data-init-value'),
    };

    // Initialize total seconds
    this.total_seconds = this.values.hours * 60 * 60 + (this.values.minutes * 60) + this.values.seconds;

    // Animate countdown to the end 
    this.count();    
  },

  count: function() {

    var that    = this,
        $hour_1 = this.$.hours.eq(0),
        $hour_2 = this.$.hours.eq(1),
        $min_1  = this.$.minutes.eq(0),
        $min_2  = this.$.minutes.eq(1),
        $sec_1  = this.$.seconds.eq(0),
        $sec_2  = this.$.seconds.eq(1);

        this.countdown_interval = setInterval(function() {

        if(that.total_seconds > 0) {

            --that.values.seconds;              

            if(that.values.minutes >= 0 && that.values.seconds < 0) {

                that.values.seconds = 59;
                --that.values.minutes;
            }

            if(that.values.hours >= 0 && that.values.minutes < 0) {

                that.values.minutes = 59;
                --that.values.hours;
            }

            // Update DOM values
            // Hours
            that.checkHour(that.values.hours, $hour_1, $hour_2);

            // Minutes
            that.checkHour(that.values.minutes, $min_1, $min_2);

            // Seconds
            that.checkHour(that.values.seconds, $sec_1, $sec_2);

            --that.total_seconds;
        }
        else {
            clearInterval(that.countdown_interval);
        }
    }, 1000);    
  },

  animateFigure: function($el, value) {

     var that         = this,
             $top         = $el.find('.top'),
         $bottom      = $el.find('.bottom'),
         $back_top    = $el.find('.top-back'),
         $back_bottom = $el.find('.bottom-back');

    // Before we begin, change the back value
    $back_top.find('span').html(value);

    // Also change the back bottom value
    $back_bottom.find('span').html(value);

    // Then animate
    TweenMax.to($top, 0.8, {
        rotationX           : '-180deg',
        transformPerspective: 300,
          ease                : Quart.easeOut,
        onComplete          : function() {

            $top.html(value);

            $bottom.html(value);

            TweenMax.set($top, { rotationX: 0 });
        }
    });

    TweenMax.to($back_top, 0.8, { 
        rotationX           : 0,
        transformPerspective: 300,
          ease                : Quart.easeOut, 
        clearProps          : 'all' 
    });    
  },

  checkHour: function(value, $el_1, $el_2) {

    var val_1       = value.toString().charAt(0),
        val_2       = value.toString().charAt(1),
        fig_1_value = $el_1.find('.top').html(),
        fig_2_value = $el_2.find('.top').html();

    if(value >= 10) {

        // Animate only if the figure has changed
        if(fig_1_value !== val_1) this.animateFigure($el_1, val_1);
        if(fig_2_value !== val_2) this.animateFigure($el_2, val_2);
    }
    else {

        // If we are under 10, replace first figure with 0
        if(fig_1_value !== '0') this.animateFigure($el_1, 0);
        if(fig_2_value !== val_1) this.animateFigure($el_2, val_1);
    }    
  }
};

function initializeCountdown ( $element ){
  let uniqueCountdown = $.extend( {}, Countdown );
  uniqueCountdown.$el = $element;

  uniqueCountdown.init();
}

$('.countdown').each( function(){
  initializeCountdown( $(this) );
});

I've changed the logic with the last function and its subsequent invocation. The method makes a copy of the Countdown to provide a unique this for each object. It then sets the $el it corresponds to before initializing. We then call this method for each of our countdown elements, and since the this is unique, each countdown will operate independently of each other and will allow for countdowns to have different starting times.

本文标签: javascriptModify countdown script to allow for multiple countdowns per pageStack Overflow