skip to Main Content

I have made an analog and digital clock project for front-end development practice. The digital clock is running correctly, but the analog clock is not working correctly. The analog clock’s minute and hour hands rotate smoothly but those two hands are jumping ahead and resetting back to the correct positions in respected seconds and minutes intervals.

Before this issue occurred I had faced another one where the minute and hour hands were not in the correct positions. After solving it the minute and hour hands both jump one minute and one hour ahead respectively (one minute more and one hour more) when the 60-second interval is completed the minute hand smoothly rotates one minute ahead but in the exact 60 seconds, it jumps one more minute ahead. In the same way, when the 60 minutes interval is done the hour hand behaves in the same way. Again the minute and hour hands reset to the correct position after 15 seconds and 15 minutes respectively.
Here are the code snippet.

const hourHand = document.getElementById('hour');
const minuteHand = document.getElementById('minute');
const secondHand = document.getElementById('second');
const digitalClock = document.getElementById('digital-clock');

// Offset variables (to correct the delay)
const offsetHours = 3; // Analog clock is 3 hours ahead
const offsetMinutes = 15; // Analog clock is 15 minutes ahead
const offsetSeconds = 15; // Analog clock is 15 seconds ahead

function updateClock() {
  const now = new Date();

  // Adjust Bangladesh time for both clocks
  const localOffset = now.getTimezoneOffset() * 60 * 1000; // Local offset in milliseconds
  const bangladeshOffset = 6 * 60 * 60 * 1000; // Bangladesh offset in milliseconds (GMT+6)
  const bangladeshTime = new Date(now.getTime() + localOffset + bangladeshOffset);

  // Get digital time components
  const digitalHours = bangladeshTime.getHours();
  const digitalMinutes = bangladeshTime.getMinutes();
  const digitalSeconds = bangladeshTime.getSeconds();

  // Adjust analog clock by subtracting the offset
  const correctedHours = (digitalHours - offsetHours + 24) % 24; // Ensure valid 24-hour format
  const correctedMinutes = (digitalMinutes - offsetMinutes + 60) % 60; // Ensure valid 60 minutes
  const correctedSeconds = (digitalSeconds - offsetSeconds + 60) % 60; // Ensure valid 60 seconds

  // Calculate degrees for the analog clock hands
  const hourDeg = (360 / 12) * (correctedHours % 12) + (30 / 60) * correctedMinutes;
  const minuteDeg = (360 / 60) * correctedMinutes + (6 / 60) * correctedSeconds;
  const secondDeg = (360 / 60) * correctedSeconds;

  // Apply rotation to analog clock hands
  hourHand.style.transform = `rotate(${hourDeg}deg)`;
  minuteHand.style.transform = `rotate(${minuteDeg}deg)`;
  secondHand.style.transform = `rotate(${secondDeg}deg)`;

  // Update the digital clock display
  const formattedHours = digitalHours < 10 ? `0${digitalHours}` : digitalHours;
  const formattedMinutes = digitalMinutes < 10 ? `0${digitalMinutes}` : digitalMinutes;
  const formattedSeconds = digitalSeconds < 10 ? `0${digitalSeconds}` : digitalSeconds;
  const amPm = digitalHours >= 12 ? 'PM' : 'AM';

  digitalClock.textContent = `${formattedHours % 12 || 12}:${formattedMinutes}:${formattedSeconds} ${amPm}`;
}

// Update the clock every 1000ms (1 second)
setInterval(updateClock, 1000);

// Initialize the clock immediately
updateClock();
body {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
  background: linear-gradient(to bottom, #f4f4f4, #ccc);
  font-family: 'Arial', sans-serif;
}

.container {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.clock {
  position: relative;
  width: 350px;
  height: 350px;
  border: 8px solid black;
  border-radius: 50%;
  background: white;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
}

.center {
  position: absolute;
  width: 12px;
  height: 12px;
  background: black;
  border-radius: 50%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.hand {
  position: absolute;
  width: 50%;
  height: 6px;
  background: black;
  top: 50%;
  left: 50%;
  transform-origin: 0%;
  /* Ensure the hand rotates from the center */
  transform: translate(-50%, -50%);
  transition: transform 0.05s ease-in-out;
}

.hand {
  position: absolute;
  width: 50%;
  height: 6px;
  background: black;
  top: 50%;
  left: 50%;
  transform-origin: 0% 50%;
  /* Rotates around the base of the hand */
  transform: translate(-50%, -50%);
  transition: transform 0.05s ease-in-out;
}

.hour {
  width: 25%;
  height: 6px;
  background: black;
}

.minute {
  width: 40%;
  height: 4px;
  background: black;
}

.second {
  background: red;
  height: 2px;
}

.numbers {
  position: absolute;
  width: 100%;
  height: 100%;
}

.number {
  position: absolute;
  width: 40px;
  height: 40px;
  text-align: center;
  line-height: 40px;
  font-size: 1.2em;
  font-weight: bold;
  color: black;
  transform-origin: center;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(calc(var(--i) * 30deg)) translateY(-140px);
}

.number:after {
  content: attr(data-number);
  display: block;
  transform: rotate(calc(var(--i) * -30deg));
}

.digital-clock {
  margin-top: 20px;
  font-size: 2em;
  font-weight: bold;
  color: black;
  text-align: center;
  background: white;
  padding: 10px 20px;
  border-radius: 10px;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
}
<div class="container">
  <!-- Analog Clock -->
  <div class="clock">
    <div class="numbers">
      <div class="number" style="--i: 1;" data-number="1"></div>
      <div class="number" style="--i: 2;" data-number="2"></div>
      <div class="number" style="--i: 3;" data-number="3"></div>
      <div class="number" style="--i: 4;" data-number="4"></div>
      <div class="number" style="--i: 5;" data-number="5"></div>
      <div class="number" style="--i: 6;" data-number="6"></div>
      <div class="number" style="--i: 7;" data-number="7"></div>
      <div class="number" style="--i: 8;" data-number="8"></div>
      <div class="number" style="--i: 9;" data-number="9"></div>
      <div class="number" style="--i: 10;" data-number="10"></div>
      <div class="number" style="--i: 11;" data-number="11"></div>
      <div class="number" style="--i: 12;" data-number="12"></div>
    </div>
    <div class="hand hour" id="hour"></div>
    <div class="hand minute" id="minute"></div>
    <div class="hand second" id="second"></div>
    <div class="center"></div>
  </div>
  <!-- Digital Clock -->
  <div class="digital-clock" id="digital-clock">
    00:00:00 AM
  </div>
</div>

2

Answers


  1. I fixed this by simply removing the % 60 from the correctedSeconds variable definition.

    const correctedSeconds = (digitalSeconds - offsetSeconds + 60)
    
    const hourHand = document.getElementById('hour');
    const minuteHand = document.getElementById('minute');
    const secondHand = document.getElementById('second');
    const digitalClock = document.getElementById('digital-clock');
    
    // Offset variables (to correct the delay)
    const offsetHours = 3; // Analog clock is 3 hours ahead
    const offsetMinutes = 15; // Analog clock is 15 minutes ahead
    const offsetSeconds = 15; // Analog clock is 15 seconds ahead
    
    function updateClock() {
      const now = new Date();
    
      // Adjust Bangladesh time for both clocks
      const localOffset = now.getTimezoneOffset() * 60 * 1000; // Local offset in milliseconds
      const bangladeshOffset = 6 * 60 * 60 * 1000; // Bangladesh offset in milliseconds (GMT+6)
      const bangladeshTime = new Date(now.getTime() + localOffset + bangladeshOffset);
    
      // Get digital time components
      const digitalHours = bangladeshTime.getHours();
      const digitalMinutes = bangladeshTime.getMinutes();
      const digitalSeconds = bangladeshTime.getSeconds();
    
      // Adjust analog clock by subtracting the offset
      const correctedHours = (digitalHours - offsetHours + 24) % 24; // Ensure valid 24-hour format
      const correctedMinutes = (digitalMinutes - offsetMinutes + 60) % 60; // Ensure valid 60 minutes
      const correctedSeconds = (digitalSeconds - offsetSeconds + 60) // Ensure valid 60 seconds
    
      // Calculate degrees for the analog clock hands
      const hourDeg = (360 / 12) * (correctedHours % 12) + (30 / 60) * correctedMinutes;
      const minuteDeg = (360 / 60) * correctedMinutes + (6 / 60) * correctedSeconds;
      const secondDeg = (360 / 60) * correctedSeconds;
    
      // Apply rotation to analog clock hands
      hourHand.style.transform = `rotate(${hourDeg}deg)`;
      minuteHand.style.transform = `rotate(${minuteDeg}deg)`;
      secondHand.style.transform = `rotate(${secondDeg}deg)`;
    
      // Update the digital clock display
      const formattedHours = digitalHours < 10 ? `0${digitalHours}` : digitalHours;
      const formattedMinutes = digitalMinutes < 10 ? `0${digitalMinutes}` : digitalMinutes;
      const formattedSeconds = digitalSeconds < 10 ? `0${digitalSeconds}` : digitalSeconds;
      const amPm = digitalHours >= 12 ? 'PM' : 'AM';
    
      digitalClock.textContent = `${formattedHours % 12 || 12}:${formattedMinutes}:${formattedSeconds} ${amPm}`;
    }
    
    // Update the clock every 1000ms (1 second)
    setInterval(updateClock, 1000);
    
    // Initialize the clock immediately
    updateClock();
    body {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      margin: 0;
      background: linear-gradient(to bottom, #f4f4f4, #ccc);
      font-family: 'Arial', sans-serif;
    }
    
    .container {
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    
    .clock {
      position: relative;
      width: 350px;
      height: 350px;
      border: 8px solid black;
      border-radius: 50%;
      background: white;
      box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
    }
    
    .center {
      position: absolute;
      width: 12px;
      height: 12px;
      background: black;
      border-radius: 50%;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    
    .hand {
      position: absolute;
      width: 50%;
      height: 6px;
      background: black;
      top: 50%;
      left: 50%;
      transform-origin: 0%;
      /* Ensure the hand rotates from the center */
      transform: translate(-50%, -50%);
      transition: transform 0.05s ease-in-out;
    }
    
    .hand {
      position: absolute;
      width: 50%;
      height: 6px;
      background: black;
      top: 50%;
      left: 50%;
      transform-origin: 0% 50%;
      /* Rotates around the base of the hand */
      transform: translate(-50%, -50%);
      transition: transform 0.05s ease-in-out;
    }
    
    .hour {
      width: 25%;
      height: 6px;
      background: black;
    }
    
    .minute {
      width: 40%;
      height: 4px;
      background: black;
    }
    
    .second {
      background: red;
      height: 2px;
    }
    
    .numbers {
      position: absolute;
      width: 100%;
      height: 100%;
    }
    
    .number {
      position: absolute;
      width: 40px;
      height: 40px;
      text-align: center;
      line-height: 40px;
      font-size: 1.2em;
      font-weight: bold;
      color: black;
      transform-origin: center;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%) rotate(calc(var(--i) * 30deg)) translateY(-140px);
    }
    
    .number:after {
      content: attr(data-number);
      display: block;
      transform: rotate(calc(var(--i) * -30deg));
    }
    
    .digital-clock {
      margin-top: 20px;
      font-size: 2em;
      font-weight: bold;
      color: black;
      text-align: center;
      background: white;
      padding: 10px 20px;
      border-radius: 10px;
      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
    }
    <div class="container">
      <!-- Analog Clock -->
      <div class="clock">
        <div class="numbers">
          <div class="number" style="--i: 1;" data-number="1"></div>
          <div class="number" style="--i: 2;" data-number="2"></div>
          <div class="number" style="--i: 3;" data-number="3"></div>
          <div class="number" style="--i: 4;" data-number="4"></div>
          <div class="number" style="--i: 5;" data-number="5"></div>
          <div class="number" style="--i: 6;" data-number="6"></div>
          <div class="number" style="--i: 7;" data-number="7"></div>
          <div class="number" style="--i: 8;" data-number="8"></div>
          <div class="number" style="--i: 9;" data-number="9"></div>
          <div class="number" style="--i: 10;" data-number="10"></div>
          <div class="number" style="--i: 11;" data-number="11"></div>
          <div class="number" style="--i: 12;" data-number="12"></div>
        </div>
        <div class="hand hour" id="hour"></div>
        <div class="hand minute" id="minute"></div>
        <div class="hand second" id="second"></div>
        <div class="center"></div>
      </div>
      <!-- Digital Clock -->
      <div class="digital-clock" id="digital-clock">
        00:00:00 AM
      </div>
    </div>
    Login or Signup to reply.
  2. I understand you, making things simple is difficult.

    I am even quite admiring that you were able to establish a "correct" display with so many complications.

    However, you should reread your code better: you declare the class hand twice in the CSS

    Warning : this code does not use transition in the movement of the hands. I am working on it, and I will bring you this final correction tomorrow, my biological clock orders me to go to bed.

    const 
      hourHand     = document.querySelector('.hand.hour')
    , minuteHand   = document.querySelector('.hand.minute')
    , secondHand   = document.querySelector('.hand.second')
    , digitalClock = document.querySelector('#digital-clock')
    , hmsDeg       = [ 360/12, 360/60, 360/60 ]
    , updateClock  =_=>
      {
      let 
        now         = new Date().toLocaleTimeString('en-US', {timeZone:  'Asia/Dhaka' })
      , [ h, m, s ] = now.match(/d+/g).map((v,i)=> Number(v) * hmsDeg[i])
        ;
      h %= 360;
      digitalClock.textContent = now;
      hourHand  .style.transform  = `rotate(${h}deg)`;
      minuteHand.style.transform  = `rotate(${m}deg)`;
      secondHand.style.transform  = `rotate(${s}deg)`;
      };
    
    updateClock();  // Initialize the clock immediately
    setInterval(updateClock, 1000);
    body {
      display         : flex;
      justify-content : center;
      align-items     : center;
      height          : 100vh;
      margin          : 0;
      background      : linear-gradient(to bottom, #f4f4f4, #ccc);
      font-family     : 'Arial', sans-serif;
      }
    .container {
      display        : flex;
      flex-direction : column;
      align-items    : center;
      }
    .analog-clock {
      position      : relative;
      --szClock     : 350px;
      width         : var(--szClock);
      height        : var(--szClock);
      border        : 8px solid black;
      border-radius : 50%;
      background    : white;
      box-shadow    : 0 4px 15px rgba(0, 0, 0, 0.3);
      }
    .center {
      position      : absolute;
      width         : 12px;
      height        : 12px;
      background    : black;
      border-radius : 50%;
      top           : 50%;
      left          : 50%;
      transform     : translate(-50%, -50%);
      }
    .hand {
      position         : absolute;
      bottom           : 50%;
      width            : 0;
      transform-origin : bottom center;
      border           : 0 solid black;
      }
    .hour {
      left               : calc(50% - 3px);
      height             : 25%;
      border-right-width : 3px;
      border-left-width  : 3px;
      }
    .minute {
      left               : calc(50% - 2px);
      height             : 36%;
      border-right-width : 2px;
      border-left-width  : 2px;
      border-color       : darkblue;
      }
    .second {
      left               : calc(50% - 1px);
      height             : 38%;
      border-right-width : 1px;
      border-left-width  : 1px;
      border-color       : crimson;
      }
    .hour-numbers {
      position      : absolute;
      width         : 100%;
      height        : 100%;
      counter-reset : hourNum;
      color         : black;
      font-weight   : bold;
      font-size     : 1.2em;
      text-align    : center;
      line-height   : 40px;
      }
    .hour-numbers > div {
      position          : absolute;
      width             : 40px;
      height            : 40px;
      transform-origin  : center;
      top               : 50%;
      left              : 50%;
      transform         : translate(-50%, -50%) rotate(calc(var(--i) * 30deg)) translateY(-140px);
      counter-increment : hourNum;
      }
    .hour-numbers > div::after {
      content   : counter(hourNum);
      display   : block;
      transform : rotate(calc(var(--i) * -30deg));
      }
    #digital-clock {
      margin-top    : 20px;
      font-size     : 2em;
      font-weight   : bold;
      color         : black;
      text-align    : center;
      background    : white;
      padding       : 10px 20px;
      border-radius : 10px;
      box-shadow    : 0 4px 10px rgba(0, 0, 0, 0.2);
      }
    <div class="container">
      <div class="analog-clock">
        <div class="hour-numbers">
          <div style="--i: 1;"  ></div>
          <div style="--i: 2;"  ></div>
          <div style="--i: 3;"  ></div>
          <div style="--i: 4;"  ></div>
          <div style="--i: 5;"  ></div>
          <div style="--i: 6;"  ></div>
          <div style="--i: 7;"  ></div>
          <div style="--i: 8;"  ></div>
          <div style="--i: 9;"  ></div>
          <div style="--i: 10;" ></div>
          <div style="--i: 11;" ></div>
          <div style="--i: 12;" ></div>
        </div>  
        <div class="hand hour" ></div> 
        <div class="hand minute"></div> 
        <div class="hand second"></div> 
        <div class="center"></div>
      </div>
      <div id="digital-clock"> 00:00:00 AM </div>
    </div> 
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search