Creating A Retro Flip Clock with jQuery And CSS3

Creating A Retro Flip Clock with jQuery And CSS3
File Size: 3.13 KB
Views Total: 3689
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   

A lightweight jQuery extension that uses CSS3 transforms to create a beautiful retro-looking flip clock displaying the current local time.

How to use it:

1. The html structure for the flip clock.

<time>
  <div class="clock">
    <div class="dial-container dial-container--hh js-clock" 
         data-cur="9" 
         data-start="0" 
         data-end="12" 
         data-dur="hh">
    </div>
    
    <div class="dial-container dial-container--mm js-clock" 
         data-cur="2" 
         data-start="0" 
         data-end="5" 
         data-dur="mm">
    </div>
    <div class="dial-container dial-container--m js-clock" 
         data-cur="3" 
         data-start="0" 
         data-end="9" 
         data-dur="m">
    </div>
    
    <div class="dial-container dial-container--ss js-clock" 
         data-cur="4" 
         data-start="0" 
         data-end="5" 
         data-dur="ss">
    </div>
    <div class="dial-container dial-container--s js-clock" 
         data-cur="8" 
         data-start="0" 
         data-end="9" 
         data-dur="s">
    </div>
  </div>
</time>

2. The primary CSS/CSS3 styles.

.transitions-off * {
  -webkit-transition: none !important;
  transition: none !important;
}

time {
  position: absolute;
  top: 150px;
  left: 0;
  right: 0;
  margin: 0;
  display: block;
  text-align: center;
}

.dial-container {
  display: inline-block;
  position: relative;
  text-align: center;
  margin: auto;
  -webkit-perspective: 1000;
  perspective: 1000;
  height: 100px;
  width: 65px;
  cursor: default;
}

.dial-container.dial-container--hh { width: 120px; }

span {
  width: 65px;
  height: 50px;
}

.dial {
  top: 0;
  height: 25px;
  /* overflow: hidden */
  -webkit-transition: all 0.6s;
  transition: all 0.6s;
  -webkit-transform-style: preserve-3d;
  transform-style: preserve-3d;
  position: absolute;
  z-index: 3;
  -webkit-transform-origin: 50px 50px;
  -ms-transform-origin: 50px 50px;
  transform-origin: 50px 50px;
}

span {
  display: block;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  position: absolute;
  top: 0;
  left: 0;
  height: 50px;
  overflow: hidden;
  background: #462c2e;
  color: #fff;
  text-align: center;
  line-height: 100px;
  font-size: 80px;
  font-weight: bold;
  border-radius: 10px 10px 0 0;
}

.dial-container--ss span,
.dial-container--mm span {
  text-align: right;
  padding-right: 2px;
  border-radius: 10px 0 0 0;
}

.dial-container--hh span {
  text-align: center;
  min-width: 120px;
}

.dial-container--s span,
.dial-container--m span {
  text-align: left;
  padding-left: 2px;
  border-radius: 0 10px 0 0;
}

span:first-child {
  z-index: 2;
  -webkit-transform: rotateY(0deg);
  transform: rotateY(0deg);
  background-color: #3c2527;
  color: #ccc;
}

span:first-child:after {
  display: block;
  width: 100%;
  height: 1px;
  background: rgba(0,0,0,0.2);
  content: ' ';
  position: absolute;
  bottom: 0;
  left: 0;
}

span:last-child {
  -webkit-transform: rotateY(180deg);
  transform: rotateY(180deg);
  border-radius: 0 0 10px 10px;
  line-height: 0;
  -webkit-transform: rotateX(180deg);
  transform: rotateX(180deg);
}

.dial-container--ss span:last-child,
.dial-container--mm span:last-child { border-radius: 0 0 0 10px; }

.dial-container--s span:last-child,
.dial-container--m span:last-child { border-radius: 0 0 10px 0; }

.dial--static,
.dial--next {
  -webkit-transform: rotateX(0deg) !important;
  transform: rotateX(0deg) !important;
}

.dial--flipped {
  z-index: 2;
  -webkit-transform: rotateX(180deg) !important;
  transform: rotateX(180deg) !important;
}

.dial--next { z-index: 2; }

.dial--later { z-index: 1; }

3. Include the latest version of jQuery library at the end of the document.

<script src="//code.jquery.com/jquery-2.1.4.min.js"></script> 

4. The core JavaScript to enable the flip clock.

(function() {
  var appendEls, attachEvents, enableTransitions, nthDigit, reset, setAttributes, setClasses, startClock, tick;

  nthDigit = function(int, nth) {
    return parseInt(int.toString().substr(nth, 1));
  };

  setAttributes = function() {
    var hours, minutes, seconds, timeNow;
    timeNow = new Date();
    hours = timeNow.getHours();
    if (hours > 12) {
      hours -= 12;
    }
    $('.js-clock[data-dur="hh"]').attr('data-cur', hours + 1);
    minutes = timeNow.getMinutes();
    if (minutes < 10) {
      $('.js-clock[data-dur="mm"]').attr('data-cur', 1);
      $('.js-clock[data-dur="m"]').attr('data-cur', minutes + 1);
    } else {
      $('.js-clock[data-dur="mm"]').attr('data-cur', nthDigit(minutes, 0) + 1);
      $('.js-clock[data-dur="m"]').attr('data-cur', nthDigit(minutes, 1) + 1);
    }
    seconds = timeNow.getSeconds();
    minutes = timeNow.getMinutes();
    if (seconds < 10) {
      $('.js-clock[data-dur="ss"]').attr('data-cur', 1.);
      return $('.js-clock[data-dur="s"]').attr('data-cur', seconds + 1);
    } else {
      $('.js-clock[data-dur="ss"]').attr('data-cur', nthDigit(seconds, 0) + 1);
      return $('.js-clock[data-dur="s"]').attr('data-cur', nthDigit(seconds, 1) + 1);
    }
  };

  tick = function($el) {
    var $active;
    $active = $el.find('.dial--active');
    $active.removeClass('dial--active');
    $active.addClass('dial--flipped');
    $active.next().removeClass('dial--next').addClass('dial--active');
    $active.next().next().addClass('dial--next').removeClass('dial--later');
    if ($active.next().hasClass('dial--last')) {
      return setTimeout((function() {
        return reset($el);
      }), 300, $el);
    }
  };

  enableTransitions = function($el) {
    return $el.removeClass('transitions-off');
  };

  reset = function($el) {
    $el.addClass('transitions-off');
    $el.children().removeClass('dial--flipped');
    $el.children().removeClass('dial--active');
    $el.children().removeClass('dial--next');
    $el.children().first().addClass('dial--active');
    $el.children(':nth-child(2)').addClass('dial--next');
    $el.children(':nth-child(n+3)').addClass('dial--later');
    setTimeout((function() {
      return enableTransitions($el);
    }), 300, $el);
    tick($el);
    if ($el.attr('data-dur') === 's') {
      $(document).trigger('10s');
    }
    if ($el.attr('data-dur') === 'ss') {
      $(document).trigger('60s');
    }
    if ($el.attr('data-dur') === 'm') {
      $(document).trigger('10m');
    }
    if ($el.attr('data-dur') === 'mm') {
      return $(document).trigger('60m');
    }
  };

  setClasses = function($el) {
    var curIndex;
    curIndex = parseInt($el.attr('data-cur'));
    $el.children(':nth-child(' + curIndex + ')').addClass('dial--active');
    $el.children(':nth-child(' + (curIndex + 1) + ')').addClass('dial--next');
    $el.children(':lt(' + curIndex + ')').addClass('dial--flipped');
    $el.children(':gt(' + curIndex + ')').addClass('dial--later');
    return tick($el);
  };

  startClock = function() {
    return setInterval(function() {
      return tick($('.js-clock[data-dur="s"]'));
    }, 1000);
  };

  appendEls = function() {
    return $('.js-clock').each(function() {
      var $el, end, k, l, start;
      $el = $(this);
      start = parseInt($(this).attr('data-start'));
      end = parseInt($(this).attr('data-end'));
      k = start;
      while (k <= end) {
        if ((k + 1) > end) {
          l = 0;
        } else {
          l = k + 1;
        }
        $el.append('<div class="dial"><span>' + k + '</span><span>' + l + '</span>');
        k++;
      }
      $el.prepend('<div class="dial"><span>0</span><span>0</span></div>');
      $el.append('<div class="dial dial--last"><span>0</span><span>0</span></div>');
      return setClasses($el);
    });
  };

  attachEvents = function() {
    $('.js-clock').on('click', function(e) {
      var $active, $el;
      e.preventDefault();
      $el = $(this);

      $active = $el.find('.dial--active');
      return tick($el);
    });
    $(document).on('10s', function() {
      return tick($('.js-clock[data-dur="ss"]'));
    });
    $(document).on('60s', function() {
      return tick($('.js-clock[data-dur="m"]'));
    });
    return $(document).on('10m', function() {
      tick($('.js-clock[data-dur="mm"]'));
      $(document).on('60m', function() {});
      return tick($('.js-clock[data-dur="hh"]'));
    });
  };

  $(document).ready(function() {
    setAttributes();
    appendEls();
    attachEvents();
    return startClock();
  });

}).call(this);

This awesome jQuery plugin is developed by paulnoble. For more Advanced Usages, please check the demo page or visit the official website.