0

I did an exercise on 30 Days of JavaScript. The exercise was to make a clock. I made the clock here on CodePen. If you play it, you will see that when the second hand reaches the top, it actually circles backward 360 degrees to go to the next second. Here is the JavaScript for this version of the clock:

const secondHand = document.querySelector('.second-hand');
const minuteHand = document.querySelector('.min-hand');
const hourHand = document.querySelector('.hour-hand');
function setDate() {
  const now = new Date();
  const seconds = now.getSeconds();
  const secondsDegrees = ((seconds / 60) * 360) + 90;
  secondHand.style.transform = `rotate(${secondsDegrees}deg)`;

  const minutes = now.getMinutes();
  const minutesDegrees = ((minutes / 60) * 360) + 90;
  minuteHand.style.transform = `rotate(${minutesDegrees}deg)`;

  const hours = now.getHours();
  const hoursDegrees = ((hours / 60) * 360) + 90;
  hourHand.style.transform = `rotate(${hoursDegrees}deg)`;
}

setInterval(setDate, 1000);

I looked at what someone else who didn't have the problem did for their clock (their CodePen is here. I changed the calculations for my secondsDegrees, minuteDegrees and hoursDegrees to match theirs. I think now, aside from the order of things, our codes are pretty much the same. However, now my second hand is circling backwards when it hits the 30 second mark. Here is my altered code:

const secondHand = document.querySelector('.second-hand');
const minuteHand = document.querySelector('.min-hand');
const hourHand = document.querySelector('.hour-hand');
function setDate() {
  const now = new Date();
  const seconds = now.getSeconds();
  const secondsDegrees = -90 + (seconds * 6);
  secondHand.style.transform = `rotate(${secondsDegrees}deg)`;

  const minutes = now.getMinutes();
  const minutesDegrees = -90 + (minutes * 360/60);
  minuteHand.style.transform = `rotate(${minutesDegrees}deg)`;

  const hours = now.getHours();
  const hoursDegrees = -90 + (hours * (360/12));
  hoursDegrees = hoursDegrees + (0.5 * minutes);
  hourHand.style.transform = `rotate(${hoursDegrees}deg)`;
}

setInterval(setDate, 1000);

Live Example (with HTML and CSS for the clock):

const secondHand = document.querySelector('.second-hand');
const minuteHand = document.querySelector('.min-hand');
const hourHand = document.querySelector('.hour-hand');

function setDate() {
  const now = new Date();
  const seconds = now.getSeconds();
  const secondsDegrees = ((seconds / 60) * 360) + 90;
  secondHand.style.transform = `rotate(${secondsDegrees}deg)`;

  const minutes = now.getMinutes();
  const minutesDegrees = ((minutes / 60) * 360) + 90;
  minuteHand.style.transform = `rotate(${minutesDegrees}deg)`;

  const hours = now.getHours();
  const hoursDegrees = ((hours / 60) * 360) + 90;
  hourHand.style.transform = `rotate(${hoursDegrees}deg)`;
}

setInterval(setDate, 1000);
html {
  background: #018DED url(http://unsplash.it/1500/1000?image=881&blur=50);
  background-size: cover;
  font-family: 'helvetica neue';
  text-align: center;
  font-size: 10px;
}

body {
  margin: 0;
  font-size: 2rem;
  display: flex;
  flex: 1;
  min-height: 100vh;
  align-items: center;
}

.clock {
  width: 30rem;
  height: 30rem;
  border: 20px solid white;
  border-radius: 50%;
  margin: 50px auto;
  position: relative;
  padding: 2rem;
  box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.1), inset 0 0 0 3px #EFEFEF, inset 0 0 10px black, 0 0 10px rgba(0, 0, 0, 0.2);
}

.clock-face {
  position: relative;
  width: 100%;
  height: 100%;
  transform: translateY(-3px);
  /* account for the height of the clock hands */
}

.hand {
  width: 50%;
  height: 6px;
  position: absolute;
  top: 50%;
  transform-origin: 100%;
  transform: rotate(90deg);
  transition: all 0.05s;
  transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
}

.hour-hand,
.min-hand {
  background: black;
}

.second-hand {
  background: red;
}
<div class="clock">
  <div class="clock-face">
    <div class="hand hour-hand"></div>
    <div class="hand min-hand"></div>
    <div class="hand second-hand"></div>
  </div>
</div>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
apex2022
  • 777
  • 2
  • 8
  • 28
  • 1
    cant reproduce the error from your CodePen – mast3rd3mon Mar 04 '19 at 14:37
  • 1
    both CodePen links working as expected... without problems – Sinisa Bobic Mar 04 '19 at 14:39
  • Please make sure **all** the code and markup needed to see your problem is **here, on-site**, not just in off-site links. Two reasons: People shouldn't have to go off-site to help you; and links rot, making the question and its answers useless to people in the future. Please put a [mcve] **in** the question (you can make it runnable with [Stack Snippets](https://meta.stackoverflow.com/questions/358992/)). More: [*How do I ask a good question?*](/help/how-to-ask) – T.J. Crowder Mar 04 '19 at 14:39
  • 1
    @mast3rd3mon the codepen he provided does reproduce the error. You have to wait until the clock pointer for the seconds reaches the top. when it does the clock pointer will freak out. – mrdeadsven Mar 04 '19 at 14:43
  • @mrdeadsven i did wait, the only odd behaviour was how jerky the minute hand appeared to be, but no 360 movements – mast3rd3mon Mar 04 '19 at 14:44
  • @mast3rd3mon hmm weird for me it does freak out. I'm testing it on Chrome, how about you? – mrdeadsven Mar 04 '19 at 14:45
  • @mrdeadsven same here, Chrome Version 73.0.3683.56 (Official Build) beta (64-bit) – mast3rd3mon Mar 04 '19 at 14:46
  • @mast3rd3mon Version 62.0.3202.94 (Official Build) (32-bit) (currently testing on work pc on which we are not able to update or self install programs...) – mrdeadsven Mar 04 '19 at 14:49
  • @mrdeadsven possibly a bug fixed in a lter update between 62 and 73 then? – mast3rd3mon Mar 04 '19 at 14:51
  • @mast3rd3mon very well possible as to how I see it now. I just tried it on my own pc and there it also works without glitches. – mrdeadsven Mar 04 '19 at 15:00
  • @T.J.Crowder I thought the JavaScript was the relevant code. Are you referring to the HTML and CSS? I will go ahead and put that in. And I will try out the Stack Snippets. But I have seen plenty of people put in links for jsfiddle to demonstrate their code problems, and I don't see them getting down voted or told they need to submit the code another way. In fact, it appears from my time on here that it is perfectly acceptable. I'm not sure why CodePen would be treated differently than jsFiddle, but I've never been able to get Fiddle to work for me. – apex2022 Mar 04 '19 at 15:20
  • @DavidTarvin - CodePen shouldn't be treated any differently to jsFiddle; both are off-site and lead to people leaving out code that people trying to help need to replicate the problem. (I didn't downvote the question, btw. My guess is the people doing so were doing it because they couldn't replicate the problem running the CodePen -- but that's a guess.) – T.J. Crowder Mar 04 '19 at 15:24
  • BTW, one problem is that you're assigning to `hoursDegrees` after initialization, but `hoursDegrees` is a constant. That error should be showing up in your web console. I doubt it relates to the second-hand problem you're seeing, though. – T.J. Crowder Mar 04 '19 at 15:28
  • Unfortunately your edit creating a snippet overwrote my edit creating a snippet. :-) Note that the code you put in your snippet is not *quite* the same as "My altered code". Specifically, it doesn't have the assigning-to-a-constant that I mentioned above. – T.J. Crowder Mar 04 '19 at 15:32
  • You won't see the second hand go all the way backwards - what you see is a jerk where for a moment the second hand appears to be on somewhere else on the clock face, usually around the thirty five to forty minute mark. I just know that it's caused by going backwards 360 degrees because I had read about this problem with the clock exercise before. Unfortunately, that did not provide a solution but only discussed the problem. – apex2022 Mar 04 '19 at 15:32
  • @mast3rd3mon - I can confirm I see that problem described by David [in his latest comment](https://stackoverflow.com/questions/54985409/second-hand-on-javascript-clock-goes-backwards#comment96730632_54985409) on Chrome v72. – T.J. Crowder Mar 04 '19 at 15:33
  • @T.J.Crowder The assigning to the constant was something I did to try to fix the code, and I only did it because the example that I looked to had it on that clock, so I didn't know if it was relevant or not. But I did not look closely, so he probably just had it as a var and not a const. In any event, whether we take it out or leave it in the problem persists. – apex2022 Mar 04 '19 at 15:35
  • @T.J.Crowder Might this be because of an performance issue with chrome? In the snippet try and take out the hour and minute code of the javascript and you will no longer see the glitch. So to me it seems because of the extra calculation for hours and minutes he does we get the glitch in older versions of chrome. – mrdeadsven Mar 04 '19 at 15:36
  • Other people's clocks don't have the glitch in the same version of chrome though. So I don't know why that would make a difference. As far as taking the minute and hour code out, if I do that then the hour and minute hands wouldn't move, right? – apex2022 Mar 04 '19 at 15:41

2 Answers2

4

The problem is the transition. You're transitioning from 444 degrees back to 90 degress when the seconds go from 59 to 0, so you see the hand briefly somewhere on the clockface as the browser applies the CSS transition.

If you disable the transition when going from 59 to 0 (e.g., back to 90 degrees), you don't see it. Note that this applies to all hands, not just seconds.

const secondHand = document.querySelector('.second-hand');
const minuteHand = document.querySelector('.min-hand');
const hourHand = document.querySelector('.hour-hand');

function setDate() {
  const now = new Date();
  const seconds = now.getSeconds();
  const secondsDegrees = ((seconds / 60) * 360) + 90;
  if (secondsDegrees == 90) {
    secondHand.classList.add("no-transition");
  } else {
    secondHand.classList.remove("no-transition");
  }
  secondHand.style.transform = `rotate(${secondsDegrees}deg)`;

  const minutes = now.getMinutes();
  const minutesDegrees = ((minutes / 60) * 360) + 90;
  if (minutesDegrees == 90) {
    minuteHand.classList.add("no-transition");
  } else {
    minuteHand.classList.remove("no-transition");
  }
  minuteHand.style.transform = `rotate(${minutesDegrees}deg)`;

  const hours = now.getHours();
  const hoursDegrees = ((hours / 60) * 360) + 90;
  if (hoursDegrees == 90) {
    hourHand.classList.add("no-transition");
  } else {
    hourHand.classList.remove("no-transition");
  }
  hourHand.style.transform = `rotate(${hoursDegrees}deg)`;
}

setInterval(setDate, 1000);
html {
  background: #018DED url(http://unsplash.it/1500/1000?image=881&blur=50);
  background-size: cover;
  font-family: 'helvetica neue';
  text-align: center;
  font-size: 10px;
}

body {
  margin: 0;
  font-size: 2rem;
  display: flex;
  flex: 1;
  min-height: 100vh;
  align-items: center;
}

.clock {
  width: 30rem;
  height: 30rem;
  border: 20px solid white;
  border-radius: 50%;
  margin: 50px auto;
  position: relative;
  padding: 2rem;
  box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.1), inset 0 0 0 3px #EFEFEF, inset 0 0 10px black, 0 0 10px rgba(0, 0, 0, 0.2);
}

.clock-face {
  position: relative;
  width: 100%;
  height: 100%;
  transform: translateY(-3px);
  /* account for the height of the clock hands */
}

.hand {
  width: 50%;
  height: 6px;
  position: absolute;
  top: 50%;
  transform-origin: 100%;
  transform: rotate(90deg);
  transition: all 0.05s;
  transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
}

.no-transition {
  transition: none;
}

.hour-hand,
.min-hand {
  background: black;
}

.second-hand {
  background: red;
}
<div class="clock">
  <div class="clock-face">
    <div class="hand hour-hand"></div>
    <div class="hand min-hand"></div>
    <div class="hand second-hand"></div>
  </div>
</div>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Nicely solved, I didn't even think of that +1 from me. Also do you have an idea why this glitch didn't occur to other people with different versions of chrome? – mrdeadsven Mar 04 '19 at 16:23
  • 1
    @mrdeadsven - I doubt the version of Chrome really matters. I think it's more likely that from the OP's original description, they expected (as I did) the hand to start moving backward, rather than just a flash briefly somewhere on the clockface. And/or vagaries of rendering on different hardware, etc. :-) – T.J. Crowder Mar 04 '19 at 16:26
0

I used this code and it works. Just keep increasing clock second degree greater than 360 deg and it works fine.

var timeinterval=null;
var srotation=null;
var newrotation=null;
function clockfunc()
{
    timeinterval=setInterval(clockdisp,1000);
    
}
function clockdisp()
{
    var d=new Date();
    var htime=d.getHours();
    var mtime=d.getMinutes();
    var stime=d.getSeconds();
    
    var hrotation=30*htime+mtime/2;
    var mrotation=6*mtime;
    if(newrotation>=354)
    {
        newrotation=newrotation+6;
    }
    
    if(srotation<354 || srotation==null)
    {
        srotation=6*stime;
        newrotation=srotation;
    }
    document.getElementById("hrhand").style.transform="rotate("+hrotation+ "deg)";
    document.getElementById("mhand").style.transform="rotate("+mrotation+ "deg)";
    document.getElementById("shand").style.transform="rotate("+newrotation+ "deg)";
    
    
}
ZygD
  • 22,092
  • 39
  • 79
  • 102