Analog Clock - Rotation

Hi there,

Problem

I have a clock model that’s been imported from Blender, it would be great if the clock showed the actual time. It seems as if the second hand is going way to fast, and If I add the hour and minute hand into the mix it goes way out of sync I’m not sure if my maths is correct or there is something else going on:

JS

function rotateClock() {
    const currentDate = new Date(),
        secondsRatio = currentDate.getSeconds() / 60,
        minutesRatio = (secondsRatio + currentDate.getMinutes()) / 60,
        hoursRatio = (minutesRatio + currentDate.getHours()) / 12;

    let secondArm = scene.children[2].children[7],
        minutesArm = scene.children[2].children[5],
        hourArm = scene.children[2].children[6]

    secondArm.rotation.x = (Date.now() / 1000 ) % 60 * 6
}

Codepen:

A full rotation around an axis in radians is Math.PI * 2.
One second’s rotation is Math.PI * 2 / 60. Your code is missing this ratio.

3 Likes

Thanks for your reply @marquizzo

So for the second hand, it should be as follows?

Math.Pi * 2 / (Date.now() / 1000 ) % 60 * 6

Thanks again.

Years ago I went that way :sweat_smile: :

http://west77.ru/content/r70/clock.html

	var date = new Date();
	var hours = date.getHours();
	var minutes = date.getMinutes();
	var seconds = date.getSeconds();
	var milliseconds = date.getMilliseconds();
	var smoothSeconds = seconds + ( milliseconds / 1000 );
	    minutes = minutes + ( smoothSeconds / 60 );
				
	hourHand.rotation.z = -THREE.Math.degToRad( 0.5 * ( (60 * hours) + minutes ) );
	minuteHand.rotation.z = -THREE.Math.degToRad( 6 * minutes );
	secondHand.rotation.z = -THREE.Math.degToRad( 6 * smoothSeconds );

Thanks for your reply @prisoner849 & @marquizzo

I have implemented both solutions below, but they seem to tick very randomly!

    //prisoner849
    var milliseconds = currentDate.getMilliseconds();
    var seconds = currentDate.getSeconds();
    var smoothSeconds = seconds + ( milliseconds / 1000 );
    secondArm.rotation.x = smoothSeconds;
  
    //marquizzo
    secondArm.rotation.x = Math.PI * 2 / secondsRatio; 

Thanks for your help.

For my option it has to be:
secondArm.rotation.x = -THREE.Math.degToRad( 6 * smoothSeconds );
Though you won’t get smooth movement of the hand as you rotate it in setInterval of 1 second, not in animation loop.

Thanks @prisoner849 that second hand is working perfectly!
Can I ask what you would reccomened for the set interval? Timeout of 1?

Also the smoothMinutes & smoothHours don’t seem to be working:

    let date = new Date(),
        hours = date.getHours(),
        minutes = date.getMinutes(),
        seconds = date.getSeconds(),
        milliseconds = date.getMilliseconds(),
        smoothSeconds = seconds + ( milliseconds / 1000 ),
        smoothMinutes = minutes + ( seconds / 1000 ),
        smoothHour = hours + ( minutes / 1000 );

    let secondArm = scene.children[2].children[7],
        minutesArm = scene.children[2].children[5],
        hourArm = scene.children[2].children[6]


   // secondArm.rotation.x = (Date.now() / 1000 ) % 60 * 6
    secondArm.rotation.x = -THREE.Math.degToRad( 6 * smoothSeconds );
    minutesArm.rotation.x = -THREE.Math.degToRad( 6 * smoothMinutes );
    hourArm.rotation.x = -THREE.Math.degToRad( 6 * smoothHour );

Do you have any ideas why?

Thanks again!