Simple Analog Clock using HTML5 canvas and JavaScript

← PrevNext →

In this article, I am going to show you how to design a simple analog clock using HTML5 canvas element and JavaScript. HTML5 canvas provides some easy to use functions and other useful features for making basic animation. However, it would not have been possible without the support of JavaScript.

Analog Clock using HTML5 Canvas and JavaScript

Did I say simple? Yes. Writing a script to design analog clock needs very little math, and trust me you don’t have to a Mathematician to understand it.

See this demo

There are "no" background images attached to this demo. It is pure JavaScript.

The most interesting part of making animation with canvas and JavaScript is that the script executes at the client side of the application. Therefore, the source code is always available for web developers to scrutinize and develop something better.

Just make sure that your browser supports HTML5 canvas element. It is important that you upgraded your browser to the latest version.

Let us get on with our clock. I'll keep it simple, and focus more on the scripting part. First, I'll add the canvas to my web page. The canvas is a square with its width and height property set to 400px each. There is no extra designing.

The Markup with the Script
<!doctype html>
<html>
<head>
    <title>Analog Clock on HTML5 Canvas and JavaScript</title>
</head>
<body>
    <canvas id="canvas" width="400" height="400"></canvas>
</body>

<script>
    window.onload = function () {
        setInterval(showClock, 1000);

        function showClock() {

            // DEFINE CANVAS AND ITS CONTEXT.
            var canvas = document.getElementById('canvas');
            var ctx = canvas.getContext('2d');

            var date = new Date;
            var angle;
            var secHandLength = 60;

            // CLEAR EVERYTHING ON THE CANVAS. RE-DRAW NEW ELEMENTS EVERY SECOND.
            ctx.clearRect(0, 0, canvas.width, canvas.height);        

            OUTER_DIAL1();
            OUTER_DIAL2();
            CENTER_DIAL();
            MARK_THE_HOURS();
            MARK_THE_SECONDS();

            SHOW_SECONDS();
            SHOW_MINUTES();
            SHOW_HOURS();

            function OUTER_DIAL1() {
                ctx.beginPath();
                ctx.arc(canvas.width / 2, canvas.height / 2, secHandLength + 10, 0, Math.PI * 2);
                ctx.strokeStyle = '#92949C';
                ctx.stroke();
            }
            function OUTER_DIAL2() {
                ctx.beginPath();
                ctx.arc(canvas.width / 2, canvas.height / 2, secHandLength + 7, 0, Math.PI * 2);
                ctx.strokeStyle = '#929BAC';
                ctx.stroke();
            }
            function CENTER_DIAL() {
                ctx.beginPath();
                ctx.arc(canvas.width / 2, canvas.height / 2, 2, 0, Math.PI * 2);
                ctx.lineWidth = 3;
                ctx.fillStyle = '#353535';
                ctx.strokeStyle = '#0C3D4A';
                ctx.stroke();
            }

            function MARK_THE_HOURS() {

                for (var i = 0; i < 12; i++) {
                    angle = (i - 3) * (Math.PI * 2) / 12;       // THE ANGLE TO MARK.
                    ctx.lineWidth = 1;            // HAND WIDTH.
                    ctx.beginPath();

                    var x1 = (canvas.width / 2) + Math.cos(angle) * (secHandLength);
                    var y1 = (canvas.height / 2) + Math.sin(angle) * (secHandLength);
                    var x2 = (canvas.width / 2) + Math.cos(angle) * (secHandLength - (secHandLength / 7));
                    var y2 = (canvas.height / 2) + Math.sin(angle) * (secHandLength - (secHandLength / 7));

                    ctx.moveTo(x1, y1);
                    ctx.lineTo(x2, y2);

                    ctx.strokeStyle = '#466B76';
                    ctx.stroke();
                }
            }

            function MARK_THE_SECONDS() {

                for (var i = 0; i < 60; i++) {
                    angle = (i - 3) * (Math.PI * 2) / 60;       // THE ANGLE TO MARK.
                    ctx.lineWidth = 1;            // HAND WIDTH.
                    ctx.beginPath();

                    var x1 = (canvas.width / 2) + Math.cos(angle) * (secHandLength);
                    var y1 = (canvas.height / 2) + Math.sin(angle) * (secHandLength);
                    var x2 = (canvas.width / 2) + Math.cos(angle) * (secHandLength - (secHandLength / 30));
                    var y2 = (canvas.height / 2) + Math.sin(angle) * (secHandLength - (secHandLength / 30));

                    ctx.moveTo(x1, y1);
                    ctx.lineTo(x2, y2);

                    ctx.strokeStyle = '#C4D1D5';
                    ctx.stroke();
                }
            }

            function SHOW_SECONDS() {

                var sec = date.getSeconds();
                angle = ((Math.PI * 2) * (sec / 60)) - ((Math.PI * 2) / 4);
                ctx.lineWidth = 0.5;              // HAND WIDTH.

                ctx.beginPath();
                // START FROM CENTER OF THE CLOCK.
                ctx.moveTo(canvas.width / 2, canvas.height / 2);   
                // DRAW THE LENGTH.
                ctx.lineTo((canvas.width / 2 + Math.cos(angle) * secHandLength),
                    canvas.height / 2 + Math.sin(angle) * secHandLength);

                // DRAW THE TAIL OF THE SECONDS HAND.
                ctx.moveTo(canvas.width / 2, canvas.height / 2);    // START FROM CENTER.
                // DRAW THE LENGTH.
                ctx.lineTo((canvas.width / 2 - Math.cos(angle) * 20),
                    canvas.height / 2 - Math.sin(angle) * 20);

                ctx.strokeStyle = '#586A73';        // COLOR OF THE HAND.
                ctx.stroke();
            }

            function SHOW_MINUTES() {

                var min = date.getMinutes();
                angle = ((Math.PI * 2) * (min / 60)) - ((Math.PI * 2) / 4);
                ctx.lineWidth = 1.5;              // HAND WIDTH.

                ctx.beginPath();
                ctx.moveTo(canvas.width / 2, canvas.height / 2);  // START FROM CENTER.
                // DRAW THE LENGTH.
                ctx.lineTo((canvas.width / 2 + Math.cos(angle) * secHandLength / 1.1),      
                    canvas.height / 2 + Math.sin(angle) * secHandLength / 1.1);

                ctx.strokeStyle = '#999';  // COLOR OF THE HAND.
                ctx.stroke();
            }

            function SHOW_HOURS() {

                var hour = date.getHours();
                var min = date.getMinutes();
                angle = ((Math.PI * 2) * ((hour * 5 + (min / 60) * 5) / 60)) - ((Math.PI * 2) / 4);
                ctx.lineWidth = 1.5;              // HAND WIDTH.

                ctx.beginPath();
                ctx.moveTo(canvas.width / 2, canvas.height / 2);     // START FROM CENTER.
                // DRAW THE LENGTH.
                ctx.lineTo((canvas.width / 2 + Math.cos(angle) * secHandLength / 1.5),      
                    canvas.height / 2 + Math.sin(angle) * secHandLength / 1.5);

                ctx.strokeStyle = '#000';   // COLOR OF THE HAND.
                ctx.stroke();
            }
        }
    }
</script>
</html>
Try it

Inside showClock() function, we have defined the canvas on which the clock is designed. A 2d context (object ctx) of the canvas will provided the necessary predefined functions for designing and animating the clock.

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
The Circles

Next, we made three circles using the canvas arc() method. We made two outer circles and one at the center of clock (looks like a dot), on which the hands are drawn and animated.

To set the color of the circles, we are using the strokeStyle property in the first to circles.

ctx.strokeStyle = '#92949C';

In the second circle however, along with the outer border, we will fill color inside the circle, to make it look like a big dot.

ctx.fillStyle = '#353535';
Mark the Hours and Seconds

We have defined two almost identical functions to mark (or draw) the Hours and Seconds inside the clock. The functions are MARK_THE_HOURS() and MARK_THE_SECONDS().

The first function loops 12 times to mark the Hours around the clock. In fact, these are lines designed at specified angles, using predefined canvas methods.

To do this, we will use two methods such as moveTo() and lineTo(). We will start drawing the line from a point using the moveTo() method. The method takes two parameters in the form or x and y coordinates (point1 and point2).

ctx.moveTo(x1, y1);

The lineTo() method will take two parameters to set a limit for the mark (or line).

ctx.lineTo(x2, y2);

To understand how these methods actually work, let us make a line, starting from position 0, 0 to 100, 100.

ctx.moveTo(0, 0);
ctx.lineTo(100, 100);
ctx.strokeStyle = 'red';
ctx.stroke();

Output

The stroke() method will complete the line.

Similarly, the second function loops 60 times to mark the Seconds around the clock, between the Hours.

The Hands (Seconds, Minutes and Hours)

The real animation is inside these functions, namely, SHOW_SECONDS(), SHOW_MINUTES() and SHOW_HOURS(). Apart from the clock’s angles and coordinates, the canvas methods inside these functions are similar to the one we used in our previous functions.

See this demo
Conclusion

Hope you have enjoyed this article and the demo. It’s a very basic design of an Analog Clock. However, you can apply different colors to the clock to make it more appealing. Please don’t forget to share it with your friends and also leave a comment, as it will help us understand your views on this article.

← PreviousNext →