Monday 28 November 2011

JavaScript: create an analogue clock with canvas

   


There's an interesting example buried in the MDM HTML5 pages, where we can create an analogue clock with JavaScript and <canvas>.

There's not much to say about it. What is interesting for us, is the way the clock is actually drawn.

The blue circle, hours and minutes marks are created using JavaScript, and the same logic is used to draw the hours, minutes and seconds arms.

All the static and moving parts of the clock are inserted into a <canvas> tag using getElementById. If the browser is not recognizing the HTML5 tag, it will only show a warning.

You can get the code from the MDM page, or copy it from here:
<script language="javascript" type="text/javascript">
    function init(){ 
      clock(); 
      setInterval(clock,1000); 
    } 
    function clock(){ 
      var now = new Date(); 
      var ctx = document.getElementById('canvas').getContext('2d'); 
      ctx.save(); 
      ctx.clearRect(0,0,150,150); 
      ctx.translate(75,75); 
      ctx.scale(0.4,0.4); 
      ctx.rotate(-Math.PI/2); 
      ctx.strokeStyle = "black"; 
      ctx.fillStyle = "white"; 
      ctx.lineWidth = 8; 
      ctx.lineCap = "round"; 
     
      // Hour marks 
      ctx.save(); 
      for (var i=0;i<12;i++){ 
        ctx.beginPath(); 
        ctx.rotate(Math.PI/6); 
        ctx.moveTo(100,0); 
        ctx.lineTo(120,0); 
        ctx.stroke(); 
      } 
      ctx.restore(); 
     
      // Minute marks 
      ctx.save(); 
      ctx.lineWidth = 5; 
      for (i=0;i<60;i++){ 
        if (i%5!=0) { 
          ctx.beginPath(); 
          ctx.moveTo(117,0); 
          ctx.lineTo(120,0); 
          ctx.stroke(); 
        } 
        ctx.rotate(Math.PI/30); 
      } 
      ctx.restore(); 
       
      var sec = now.getSeconds(); 
      var min = now.getMinutes(); 
      var hr  = now.getHours(); 
      hr = hr>=12 ? hr-12 : hr; 
     
      ctx.fillStyle = "black"; 
     
      // write Hours 
      ctx.save(); 
      ctx.rotate( hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec ) 
      ctx.lineWidth = 14; 
      ctx.beginPath(); 
      ctx.moveTo(-20,0); 
      ctx.lineTo(80,0); 
      ctx.stroke(); 
      ctx.restore(); 
     
      // write Minutes 
      ctx.save(); 
      ctx.rotate( (Math.PI/30)*min + (Math.PI/1800)*sec ) 
      ctx.lineWidth = 10; 
      ctx.beginPath(); 
      ctx.moveTo(-28,0); 
      ctx.lineTo(112,0); 
      ctx.stroke(); 
      ctx.restore(); 
       
      // Write seconds 
      ctx.save(); 
      ctx.rotate(sec * Math.PI/30); 
      ctx.strokeStyle = "#D40000"; 
      ctx.fillStyle = "#D40000"; 
      ctx.lineWidth = 6; 
      ctx.beginPath(); 
      ctx.moveTo(-30,0); 
      ctx.lineTo(83,0); 
      ctx.stroke(); 
      ctx.beginPath(); 
      ctx.arc(0,0,10,0,Math.PI*2,true); 
      ctx.fill(); 
      ctx.beginPath(); 
      ctx.arc(95,0,10,0,Math.PI*2,true); 
      ctx.stroke(); 
      ctx.fillStyle = "#555"; 
      ctx.arc(0,0,3,0,Math.PI*2,true); 
      ctx.fill(); 
      ctx.restore(); 
     
      ctx.beginPath(); 
      ctx.lineWidth = 14; 
      ctx.strokeStyle = '#325FA2'; 
      ctx.arc(0,0,142,0,Math.PI*2,true); 
      ctx.stroke(); 
     
      ctx.restore(); 
    } 
</script>
The above goes into the head of your page.
The <body> tag should be changed to:
<body onload="init();">
And finally, just insert the canvas where we want to show the clock:
<canvas id="canvas">The canvas is not supported by your browser</canvas>
And that's all.

1 comment:

Comments are moderated. I apologize if I don't publish comments immediately.

However, I do answer to all the comments.