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>
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>