Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

transition of second-hand in a CSS analog clock from sec==59 to 0

I want to have a smooth transition of the second-hand from sec==59 to sec==0.

It's going well from 0 to 59 seconds but on sec==59 it doesn't go forward instead it rolls back to 0 position. I'm trying to have a smooth transition from 59 to 0 in clockwise direction (same in second, minute and hour hands). Here's is the full code of the clock -

let secHand = document.querySelector(".sec-hand")
let minHand = document.querySelector(".min-hand")
let hourHand = document.querySelector(".hour-hand")
let hands = document.querySelectorAll(".hand")

function setTime() {
  const now = new Date();
  const sec = now.getSeconds();
  const secDegrees = ((sec / 60) * 360) + 90;
  secHand.style.transform = `rotate(${secDegrees}deg)`;

  const mint = now.getMinutes();
  const mintDegrees = ((mint / 60) * 360) + 90;
  minHand.style.transform = `rotate(${mintDegrees}deg)`;

  const hour = now.getHours();
  const hourDegrees = ((hour / 12) * 360) + 90;
  hourHand.style.transform = `rotate(${hourDegrees}deg)`;

  //console.log(`${hour} : ${mint} : ${sec}`)
}
setInterval(setTime, 1000)
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.clock {
  background: transparent;
  width: 400px;
  height: 400px;
  margin: auto;
  margin-top: 100px;
  border-radius: 50%;
  border: 20px solid blue;
  position: absolute;
  left: 200px;
}

.center-dot {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: rgb(195, 4, 4);
  position: absolute;
  top: calc(50% - 25px);
  left: calc(50% - 25px);
  z-index: 5;
}

.hand {
  width: 45%;
  height: 10px;
  background: black;
  position: absolute;
  top: calc(50% - 5px);
  left: 5%;
  border-radius: 10px;
  transform-origin: right;
  transition: all 0.5s;
  transform: rotate(90deg)
}
<div class="clock">
  <div class="center-dot"></div>
  <div class="hour-hand hand"></div>
  <div class="min-hand hand"></div>
  <div class="sec-hand hand"></div>
</div>

I was following a video on this and in that, tutor mentioned two solutions- first was keep counting continuously after sec=59 and not going back to sec=0 (but I didn't like this solution). Second was temporarily remove transition when on sec==59 through JS. I don't know how to do that. I tried this in setTime() but didn't work -

if(sec == 59) {
        hands[2].setAttribute("transition", "");
    }

Please help. Thank you!

like image 940
Sagar Mavai Avatar asked Oct 21 '25 08:10

Sagar Mavai


2 Answers

Off Topic: (almost) CSS only.

You only have to set the current time once with JS.

document.body.style.setProperty("--time", Math.floor(Date.now() / 1000  - new Date().getTimezoneOffset() * 60) % (60 * 60 * 24));
@keyframes turn {
  from {
    transform: rotate(90deg);
  }
  to {
    transform: rotate(450deg);
  }
}

.sec-hand {
  /*animation: turn 60s infinite steps(60);*/
  animation: turn 60s infinite linear;
  animation-delay: calc(var(--time) * -1s);
}

.min-hand {
  /*animation: turn 3600s infinite steps(60);*/
  animation: turn 3600s infinite linear;
  animation-delay: calc(var(--time) * -1s);
}

.hour-hand {
  /*animation: turn 43200s infinite steps(12);*/
  animation: turn 43200s infinite linear;
  animation-delay: calc(var(--time) * -1s);
}

downside: the lack of options regarding easing functions. You can let the clock-handles run continously, or stepped (once a second/minute/hour) but there is no stepped with easing between the steps.

document.body.style.setProperty("--time", Math.floor(Date.now() / 1000  - new Date().getTimezoneOffset() * 60) % (60 * 60 * 24));
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.clock {
  background: transparent;
  width: 400px;
  height: 400px;
  margin: auto;
  margin-top: 100px;
  border-radius: 50%;
  border: 20px solid blue;
  position: absolute;
  left: 200px;
}

.center-dot {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: rgb(195, 4, 4);
  position: absolute;
  top: calc(50% - 25px);
  left: calc(50% - 25px);
  z-index: 5;
}

.hand {
  width: 45%;
  height: 10px;
  background: black;
  position: absolute;
  top: calc(50% - 5px);
  left: 5%;
  border-radius: 10px;
  transform-origin: right;
}




@keyframes turn {
  from {
    transform: rotate(90deg)
  }
  to {
    transform: rotate(450deg)
  }
}

.sec-hand {
  --animation: turn 60s infinite steps(60);
  animation: turn 60s infinite linear;
  animation-delay: calc(var(--time) * -1s);
}

.min-hand {
  --animation: turn 3600s infinite steps(60);
  animation: turn 3600s infinite linear;
  animation-delay: calc(var(--time) * -1s);
}

.hour-hand {
  --animation: turn 43200s infinite steps(12);
  animation: turn 43200s infinite linear;
  animation-delay: calc(var(--time) * -1s);
}
<div class="clock">
  <div class="center-dot"></div>
  <div class="hour-hand hand"></div>
  <div class="min-hand hand"></div>
  <div class="sec-hand hand"></div>
</div>
like image 86
Thomas Avatar answered Oct 24 '25 00:10

Thomas


you need record secCount, mintCount, hourCount

let secHand = document.querySelector('.sec-hand') ;
let minHand = document.querySelector('.min-hand') ;
let hourHand = document.querySelector('.hour-hand') ;
let hands = document.querySelectorAll('.hand');


const delay = async (n = 0) => new Promise((res) => setTimeout(res, n));

(async () => {
  let secCount = 0;
  let mintCount = 0;
  let hourCount = 0;
  for (;;) {
    const now = new Date();
    const sec = now.getSeconds();
    const mint = now.getMinutes();
    const hour = now.getHours();
    if (sec == 0) {
      secCount++;
      if (mint == 0) {
        mintCount++;
        if (hour == 0) {
          hourCount++;
        }
      }
    }
    const secDegrees = (sec / 60 + secCount) * 360 + 90;
    secHand.style.transform = `rotate(${secDegrees}deg)`;

    const mintDegrees = (mint / 60 + mintCount) * 360 + 90;
    minHand.style.transform = `rotate(${mintDegrees}deg)`;

    const hourDegrees = (hour / 12 + hourCount) * 360 + 90;
    hourHand.style.transform = `rotate(${hourDegrees}deg)`;
    await delay(1000);
  }
})();
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.clock {
  background: transparent;
  width: 400px;
  height: 400px;
  margin: auto;
  margin-top: 100px;
  border-radius: 50%;
  border: 20px solid blue;
  position: absolute;
  left: 200px;
}

.center-dot {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: rgb(195, 4, 4);
  position: absolute;
  top: calc(50% - 25px);
  left: calc(50% - 25px);
  z-index: 5;
}

.hand {
  width: 45%;
  height: 10px;
  background: black;
  position: absolute;
  top: calc(50% - 5px);
  left: 5%;
  border-radius: 10px;
  transform-origin: right;
  transition: all 0.5s;
  transform: rotate(90deg)
}
<div class="clock">
  <div class="center-dot"></div>
  <div class="hour-hand hand"></div>
  <div class="min-hand hand"></div>
  <div class="sec-hand hand"></div>
</div>
like image 42
lisonge Avatar answered Oct 23 '25 23:10

lisonge



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!