#js30.02: Clock

Wes Bos’ Javascript30 course Project #2 is a css & js analog clock, mainly a lesson in how the Date object can be used in javascript. The use of css transforms – specifically the transform-origin attribute – is also central to achieving the clock’s hands.

The clock face and clock hands are created using pretty straightforward html & css:

  • the clock face is a div (with a 50% border-radius if one wants a round clock face),
  • the clock hands are created using empty divs, each with a small height value, and varying width values for appropriate lengths for hour hand, minute hand, second hand
  • css transform is used to rotate the ‘hands’

The javascript is a single ‘setClock’ function, pretty much all based on values derived from the Date object. Variables are defined for the clock hand elements:


const hoursHand = document.querySelector(".hours-hand");
const minutesHand = document.querySelector(".minutes-hand");
const secondsHand = document.querySelector(".seconds-hand");

Then, based on a Date object, set variables for the seconds, minutes and the hour, and with a bit of math, convert these values into clock degrees (the “+ 90” in the degrees variables is to rotate the divs appropriately):


// hours, minutes, seconds
const now = new Date();
const seconds = now.getSeconds() + 1; // compensate for 1sec delay
const secondsDegrees = ((seconds / 60) * 360) + 90;
const minutes = now.getMinutes();
const minutesDegrees = ((minutes / 60) * 360) + 90;
const hours = now.getHours();
const hoursDegrees = ((hours / 12) * 360) + 90; // √ but lo-rez

And add statements which will set the clock hands accordingly:


secondsHand.style.transform = `rotate(${secondsDegrees}deg)`;
minutesHand.style.transform = `rotate(${minutesDegrees}deg)`;
hoursHand.style.transform = `rotate(${hoursDegrees}deg)`;

Finally (well, not quite), call the function every second:


setInterval(setClock, 1000);

Now this resulted in a functioning clock but one with some buggy characteristics, e.g.:

  • neither the hour hand nor the minute hand would advance when the second hand reached 0sec but rather when the second hand reached 1sec; this was somewhat novel but inarguably inaccurate
  • the resolution of the hour hand was unacceptably coarse: it would point precisely to the current hour through the entire hour, rather than advance proportionally
  • also, because a transition effect was added to subtly animate the second hand, it would jump backwards from 0sec to 1sec (this was actually a novel effect but being on a quest for knowledge here it had to be resolved)

All these behaviors occurred when the second hand was in transition from 59s to 0s or from 0s to 1s, so I set a few variables with adjusted rotation values and then added an if/else statement:


const minutesDegreesAdj = ((minutes / 60) * 360) + 96;
const percentHour = parseFloat(minutes / 60).toFixed(2); // toFixed() returns a string!
const hoursSubDegrees = hoursDegrees + + (percentHour * 360 / 12);
const hoursSubDegreesAdj = hoursSubDegrees + + 0.3;

if (secondsDegrees == 450) { // 450 is @ '12'
   // prevent the backwards rotation from 0sec to 1sec:
   secondsHand.style.transition = "none";
   secondsHand.style.transform = `rotate(90deg)`;
   // advance the minute hand appropriately:
   minutesHand.style.transform = `rotate(${minutesDegreesAdj}deg)`;
   // advance the hour hand appropriately:
   hoursHand.style.transform = `rotate(${hoursSubDegreesAdj}deg)`;
}
else { // at all other 'seconds'
   // restore CSS transition animation:
   secondsHand.style.transition = "all .6s cubic-bezier(0, 1.8, .9, .99)";
   secondsHand.style.transform = `rotate(${secondsDegrees}deg)`;
   minutesHand.style.transform = `rotate(${minutesDegrees}deg)`;
   // advance the hour hand appropriately, per the min. hand pos.:
   hoursHand.style.transform = `rotate(${hoursSubDegrees}deg)`;
}

If anyone is interested in the details, check out the source of my version of the clock which is thoroughly commented.

And btw, Wes’ clock lesson goes only far enough to get a functioning clock; I dressed it up with clock face numbers – a dozen absolutely positioned elements, each with an :after pseudo-element containing the clock face number.

This was a fairly simple but gratifying project.