Javascript 30 — Day 2: CSS + JS Clock
I’ve learned quite a few things on my first day of doing this challenge. The thing with Wes is that he usually teaches you something in one video, to then continue on that path in the next. I absolutely love that because it means I’ll ‘get it’ a lot faster. If you haven’t read the first part yet, you can check it out here.
Check out all the other days over at my table of contents!
Today’s project is…
For those of you who don’t have the object that is displayed in the image above hanging on your wall (like me), it’s a clock. It’s got three hands: seconds, minutes and hours. Okay yeah, I know we all know it’s a clock. But most of us use our phones anyway, right?
What Wes did for this video was great. He guided me through setting up the seconds hand first and then pretty much went: “Okay, now do the other two yourself”. Granted, all three of them have the exact same setup but that’s beside the point.
What strikes me most is the way you approach this. It’s a way of thinking. Let’s start with the seconds hand. We need that thing to move every second. Obviously we’ll put everything we need inside a function, but we then need to run that function every second. The most common way to do that is with a setInterval
with which we call a function every 1000ms.
function moveHands() {}setInterval(moveHands, 1000)
Now we need to check for the current time. Javascript has a built in method to check for the current date. This isn’t new to me, but the Date()
instance can be confusing. Luckily there’s a few methods we can use to make it easier to use.
To get the seconds, minutes and hours here’s what you do:
const seconds = now.getSeconds();
const minutes = now.getMinutes();
const hours = now.getHours();
Now to turn the hands based on the time, we first need to set the transform-origin
because by default the origin from which we transform an element is from the center (or 50%). All of our hands are positioned in such a way that we want to transform them from the right, so we set transform-origin: 100%
and transform: rotate(90deg)
to make sure the hands are facing upwards at 12 o’clock.
To calculate the degrees the hands need to be set at we do the following:
const secondsDegrees = ((seconds/60) * 360) + 90;
It’s a basic percentage calculation. Part divided by whole times 100%, or in this case 360 degrees. We add the 90 degrees because we’ve offset all of the hands 90 degrees to turn them upwards.
To turn the hands we add an inline style using Javascript with the following code:
secondHand.style.transform = `rotate(${secondsDegrees}deg)`
Not only can we add classes to our elements using Element.classList.add
but we can also add inline styles using Element.style
. If you’re interested, you can check HTMLElement.style over on MDN to read about the ways you can use it. In our case we are adding the property that we want to change directly to the method.
That’s basically it. Repeat the same steps for minutes and hours (remember to divide by 12 instead of 60) and you’re good to go.
One more thing
So right before the video ends, Wes shows me this little “glitch”. Whenever the seconds hand hits zero, the hands have this little reset they do. This is because going from 450 degrees (60 seconds) to 90 degrees (0 seconds) causes the hand to go backwards. Because of the transition: all 0.05s
property it transitions it and causes the visible glitch. He goes on to talk about a few if/else
statements would fix this so I took on the challenge.
I started out with the seconds hand. This is the most recurring of the three, so I figured this one would be the easiest to solve. Or rather, the quickest as I don’t have to tinker in the dev tools.
if(secondsDegrees === 90) {
secondHand.style.transition = 'none'
} else {
secondHand.style.transition = ''
}
Okay so what I do here is check if the secondsDegrees
equals 90 or not. I wasn’t sure if it would be 90 or 450, but a simple test was all it took. When the hand resets to 90 is when the glitch happens so that’s where I want to change the transition.
side note: secondHand.style.transition = ''
resets the inline style by removing it so the element can revert back to the stylesheet.
Now that I got it working for my secondsHand, I had to make it work for the other two. That’s when I noticed something: the other two also glitch when the seconds hand hits the 90 degrees mark. That got me thinking: the other two hands really only move when the seconds hand hits 60 seconds. So I can easily solve this with a single if/else
statement.
Outside of the function I create a variable that holds all of the hands:
const allHands = document.querySelectorAll('.hand')
In the previous lesson I learned about querySelector
to select the first element it matches and querySelectorAll
to select all of the matched elements. Now it’s just a matter of looping over them using forEach
and you’re done:
if(secondsDegrees === 90) {
allHands.forEach(hand => hand.style.transition = 'none')
} else {
allHands.forEach(hand => hand.style.transition = '')
}
TIL (Today I Learned)
- You can easily set inline styles using
Element.style
- Transforming an element is, by default, at the center
- Setting
Element.style.Property = ''
resets the styling
I think today’s exercise is a small, but fun little thing to help you understand that even a minor thing such as adding inline styles can be done using Javascript. Making a simple clock won’t take you more than half an hour.
All of my code can be found at GitHub.
Check out all the other days over at my table of contents!
I know Wes’ teaching style and he is a great teacher. If you want to become more comfortable with Javascript, go check out his free course at javascript30.com.
Until next time!