Skip to content

Instantly share code, notes, and snippets.

@brokenmass
Last active April 21, 2019 23:24
Show Gist options
  • Save brokenmass/39225b0b8c21bc75966b428cdc7d7951 to your computer and use it in GitHub Desktop.
Save brokenmass/39225b0b8c21bc75966b428cdc7d7951 to your computer and use it in GitHub Desktop.
const secondHand = document.querySelector('.sec-hand');
const minsHand = document.querySelector('.min-hand');
const hourHand = document.querySelector('.hour-hand');
function calculateAngle(value, steps) {
return Math.round(90 + (value / steps) * 360);
}
function forceRepaint(element) {
element.style.display='none';
// no need to store the following anywhere. retrieving the reference is enough, but is a critical step
// otherwise the js engine might optimise the execution and skip the repaint.
element.offsetHeight;
element.style.display='block';
}
function renderDate() {
const now = new Date();
const seconds = now.getSeconds();
const mins = now.getMinutes();
const hour = now.getHours();
if(seconds === 0) {
// To avoid visual glitches you have to do an instantaneous transition from the 59s hand position
// to the (equivalen) '-1s' position before performing the transition to the 0s position.
// To achieve this using js, a solution is to set transition to '0s all' (hence disabling any animation),
// set the position of the hand to -1s, force a repaint so that the browser repaint it
// even if we are in the middle of js code execution, and finally revert the transition property to the original
// value.
// At this point he normal cicle will ensure that a 'smooth' transition from the -1s to 0s occurs.
secondHand.style.transition = "all 0s";
secondHand.style.transform = `rotate(${calculateAngle(-1, 60 )}deg)`;
forceRepaint(secondHand);
secondHand.style.transition = "";
if(mins === 0) {
// Here we just moved from hh:59:59 to (hh+1):00:00 so we also have to 'reset' the minutes handle
minsHand.style.transition = "all 0s";
minsHand.style.transform = `rotate(${calculateAngle(-1/60, 60 )}deg)`;
forceRepaint(minsHand);
minsHand.style.transition = "";
if(hours % 12 === 0) {
// here we just moved from 11:59:59 to 00:00:00 so we also have to 'reset' the hours handle
hourHand.style.transition = "all 0s";
hourHand.style.transform = `rotate(${calculateAngle(-1/3600, 12 )}deg)`;
forceRepaint(hourHand);
hourHand.style.transition = "";
}
}
}
const secondsDegrees = calculateAngle(seconds, 60 );
secondHand.style.transform = `rotate(${secondsDegrees}deg)`;
const minsDegrees = calculateAngle(mins + seconds/60, 60);
minsHand.style.transform = `rotate(${minsDegrees}deg)`;
const hourDegrees = calculateAngle(hour + mins/60 + seconds/3600, 12);
hourHand.style.transform = `rotate(${hourDegrees}deg)`;
}
setInterval(renderDate, 1000)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment