VRx js.vrx.palo-alto.ca.us

Jon Combe | Code | HTML clocks using JavaScript and CSS rotation

HTML clocks using JavaScript and CSS rotation

February 2010

Warning: This isn't going to work in any currently available version of Internet Explorer* or many older browsers.

The two clocks below are just HTML. There are no Adobe Flash files or my beloved <canvas> going on, just regular <div> and <img> tags. The way it works is by taking those images in an { overflow: hidden } <div> and rotating them, via JavaScript, using the proposed CSS transform property.


Clock second-handClock minute-handClock hour-hand
Clocks hoursClocks minutesClocks seconds
 
 

Background

In July last year, the excellent Jonathan Snook wrote an article about CSS rotation. If you're interested stuff like this and you haven't heard of Mr. Snook before, I suggest you read his stuff.

He explains in his article that the Webkit (Google Chrome & Safari) and Firefox 3.5+ browsers support the CSS transform property. Since then, Opera has joined the party too.

He also notes that it is also possible to implement basic (0° / 90° / 180° / 270°) rotations using Internet Explorer, but clearly this wasn't going to cut it for what I wanted to do here.

The code to make the clocks work is really very simple. To do the rotation, simply use the following CSS declarations:

transform: rotate(42deg);             // this won't work yet, but one day it may
-moz-transform: rotate(42deg);        // mozilla specific
-o-transform: rotate(42deg);          // opera specific
-webkit-transform: rotate(42deg);     // webkit specific

In jQuery that could look like:

$("#myElement").css({
    'transform': 'rotate(42deg)',
    '-moz-transform': 'rotate(42deg)',
    '-o-transform': 'rotate(42deg)',
    '-webkit-transform': 'rotate(42deg)'
});

How it works

I don't really see the need to breakdown the code of the clocks themselves as JavaScript clocks have been around since, well, forever. However, I will quickly explain how it works should you want to inspect the code further.

Originally, my code had one setInterval() timer that simply performed the required rotation(s) each second. Whilst it proved the concept was doable, it's jerkiness lacked the final effect I was after.

To create a smoother animation, there are now two setInterval() timers.

The first one runs once every second and updates the current time. It decides if each element (i.e. hours, minutes, seconds) is rotated to the correct angle and, if not, calculates the number of small steps it needs to take to get there. It pushes the value of these steps into an array.

For example, let's say one of my images is currently rotated 12° but it should be turned to 18°. This step pushes the numbers 13, 14, 15, 16, 17 and 18 into that element's array. These are the small, incremental animation steps which, when animated, will look nicer than an abrupt jump from 12° to 18°.

The second setInterval() timer runs must faster and is responsible for actually rotating the images. Each time it is run, it looks at each element and it if it's array is not empty it:

  1. takes the first value from that array (in our example, array[0] = 13) and rotates that image to 13° accordingly, and
  2. uses array.slice() to remove the first item from the array (in our example, the number 13).

The next time this is run, array[0] now equals 14, and the image is rotated again.

This process goes on until the array is empty. Each second the array is repopulated again by the first timer and the animation process starts again.



A couple of things to note

* Disclaimer #1:
You can rotate elements in Internet Explorer (version 5.5 and up) by arbitary amounts. All the code you need to do this is described on the MSDN website (in particular, see their function fnSetRotation(oObj, deg) example).

However, whilst the CSS3 transform: rotate spins an element around it's centre, the IE only 'matrix filters' rotate elements around their top left corner. This can be coded around by simply setting top and left absolute position attributes to keep the element centered after each rotation, but when I implemented this with my clocks, the animation wobbled about in a comical fashion. IE definitely hasn't failed here: there are many more transformations that can be applied using Microsoft's browser, but sadly, in this example, it didn't quite do what I would have liked it to do.

** Disclaimer #2:
I'm a frequent visitor to the website reddit.com and I was very happy that a link on that site to this page generated so much traffic for me. However, in response to those criticising excessive memory usage, cross browser support etc.: this is just an experiment, not (yet, unlikely ever) a sane way to display a clock on a webpage.

You're right that I missed Opera and that is fixed now.