Search code examples
javascriptjquerytimetimercountdown

Converting seconds in mm:ss in running JavaScript Timer


I'm just trying to update a friend's timer, which we did for an event a while ago. The timer works perfectly and already does everything it should (see and run Snippet). However, now I would like to display the format mm:ss instead of only seconds (eg. 180 -> 3:00). This must of course be able to count down further. Different approaches I googled have failed. Has anyone an idea how to solve my problem elegantly?

Edit: You can start and stop the timer by pressing 'Space'

<!DOCTYPE html>
<html>

<head>
  <title></title>

  <style type="text/css">
    body {
      background-color: #333;
      font-family: sans-serif;
    }
    
    .item {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translateX(-50%) translateY(-50%) scale(3.0);
    }
    
    .item h1 {
      text-align: center;
      position: absolute;
      width: 100%;
      top: 50%;
      left: 50%;
      transform: translateX(-50%) translateY(-110%);
      color: #ffffff;
      font-size: 3em;
    }
    
    .item h2 {
      text-align: center;
      position: absolute;
      width: 50%;
      top: 50%;
      left: 50%;
      transform: translateX(-50%) translateY(-110%);
      color: #ffffff;
      font-size: 1.5em;
      line-height: 0.9;
    }
    
    svg {
      -webkit-transform: rotate(-90deg);
      transform: rotate(-90deg);
    }
    
    .circle_animation {
      stroke-dasharray: 440;
      /* this value is the pixel circumference of the circle */
      stroke-dashoffset: 440;
      transition: all 1s linear;
    }
  </style>

  <script src="https://code.jquery.com/jquery-2.2.1.min.js"></script>

  <script type="text/javascript">
    var running = false;

    var time = 180;
    var initialOffset = '440';
    var runtime = 0;

    $(document).keydown(function(e) {

      switch (e.which) {
        case 32:
          setTimeout(function() {
            if (running === false) {
              running = true;
            } else {
              running = false;
            };
          }, 1);
          break;
      }
    });

    $(document).ready(function() {

      console.log("ready!");
      $('#start').click(function() {
        running = true;
      });

      var interval = setInterval(function() {
        $('.circle_animation').css('stroke-dashoffset', initialOffset - (runtime * (initialOffset / (time + 10.5))));
        $('h1').text(time - runtime);
        if (runtime == 420) {
          audioElement1.play();
        }
        if (runtime == time) {
          clearInterval(interval);
          $('.circle_animation').css('stroke-dashoffset', 880);
          $('h1').text('');
          $('h2').text('Time is up!');
        }
        if (running) {
          runtime++;
        };
      }, 1000);

    });
  </script>

</head>

<body>

  <div class="item html">
    <svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
      <g>
        <title>Layer 1</title>
        <circle id="circle" r="65.85699" cy="81" cx="81" stroke-width="15" stroke="#ffffff" fill="none"/>
        <circle id="circle" class="circle_animation" r="65.85699" cy="81" cx="81" stroke-width="16" stroke="#333" fill="none"/>
      </g>
    </svg>
    <h1>180</h1>
    <h2></h2>
  </div>

</body>

</html>


Solution

  • Use modulus math:

    function sec2human(seconds) {
        sec = seconds % 60;
        min = parseInt(seconds / 60);
        if(sec.toString().length == 1) { // padding
            sec = "0" + sec;
        }
        return min + ":" + sec;
    }
    

    Full working example:

    <!DOCTYPE html>
    <html>
    
    <head>
      <title></title>
    
      <style type="text/css">
        body {
          background-color: #333;
          font-family: sans-serif;
        }
    
        .item {
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translateX(-50%) translateY(-50%) scale(3.0);
        }
    
        .item h1 {
          text-align: center;
          position: absolute;
          width: 100%;
          top: 50%;
          left: 50%;
          transform: translateX(-50%) translateY(-110%);
          color: #ffffff;
          font-size: 3em;
        }
    
        .item h2 {
          text-align: center;
          position: absolute;
          width: 50%;
          top: 50%;
          left: 50%;
          transform: translateX(-50%) translateY(-110%);
          color: #ffffff;
          font-size: 1.5em;
          line-height: 0.9;
        }
    
        svg {
          -webkit-transform: rotate(-90deg);
          transform: rotate(-90deg);
        }
    
        .circle_animation {
          stroke-dasharray: 440;
          /* this value is the pixel circumference of the circle */
          stroke-dashoffset: 440;
          transition: all 1s linear;
        }
      </style>
    
      <script src="https://code.jquery.com/jquery-2.2.1.min.js"></script>
    
      <script type="text/javascript">
        var running = false;
    
        var time = 180;
        var initialOffset = '440';
        var runtime = 0;
    
        $(document).keydown(function(e) {
    
          switch (e.which) {
            case 32:
              setTimeout(function() {
                if (running === false) {
                  running = true;
                } else {
                  running = false;
                };
              }, 1);
              break;
          }
        });
    
        $(document).ready(function() {
    
          console.log("ready!");
          $('#start').click(function() {
            running = true;
          });
    
          $('h1').text(sec2human(time)); // added for initial display
    
          var interval = setInterval(function() {
            $('.circle_animation').css('stroke-dashoffset', initialOffset - (runtime * (initialOffset / (time + 10.5))));
            $('h1').text(sec2human(time - runtime)); // added function call
            if (runtime == 420) {
              audioElement1.play();
            }
            if (runtime == time) {
              clearInterval(interval);
              $('.circle_animation').css('stroke-dashoffset', 880);
              $('h1').text('');
              $('h2').text('Time is up!');
            }
            if (running) {
              runtime++;
            };
          }, 1000);
    
        });
    
        function sec2human(seconds) {
            sec = seconds % 60;
            min = parseInt(seconds / 60);
            if(sec.toString().length == 1) { // padding
                sec = "0" + sec;
            }
            return min + ":" + sec;
        }
      </script>
    
    </head>
    
    <body>
    
      <div class="item html">
        <svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
          <g>
            <title>Layer 1</title>
            <circle id="circle" r="65.85699" cy="81" cx="81" stroke-width="15" stroke="#ffffff" fill="none"/>
            <circle id="circle" class="circle_animation" r="65.85699" cy="81" cx="81" stroke-width="16" stroke="#333" fill="none"/>
          </g>
        </svg>
        <h1>180</h1>
        <h2></h2>
      </div>
    
    </body>
    
    </html>