HTML Canvas - Canvas Clock



Canvas clock is mostly used to add clock features to the website. Most of the websites available today use the Canvas element to implement time-based applications on their sites as it is very easy to implement, and Canvas can make good client-side animations.

We will build a real-time analog clock in this chapter. Let us draw a basic Canvas with a circle in it so that we can make an analog clock using JavaScript. The code is given below.

<!DOCTYPE html>
<html lang="en">
   <head>
      <title>canvas clock</title>
   </head>
   <body onload="clock();">
      <canvas id="canvas" width="400" height="400" style="border: 10px solid black;background-color: burlywood;"></canvas>
      <script>
         var canvas = document.getElementById("canvas");
         var context = canvas.getContext("2d");
         var radius = canvas.height / 2;
         context.translate(radius, radius);
         radius = radius * 0.90;
         Clock();

         function Clock() {
            context.arc(0, 0, radius, 0, 2 * Math.PI);
            context.lineWidth = 15;
            context.strokeStyle = "black";
            context.stroke();
            context.fillStyle = "#dddddd";
            context.fill();
         }
      </script>
   </body>
</html>

This returns the body of canvas as

Canvas Clock

Adding a face to Canvas

We must draw a canvas first and then draw circle using arc inside the canvas where we can implement the clock. To draw the circle, we have to make sure the center of canvas is the center point of the circle which helps us to make it look better. Following code draws the Canvas element and implements clock face into it.

<!DOCTYPE html>
<html lang="en">
   <head>
      <title>canvas clock</title>
   </head>
   <body onload="clock();">
      <canvas id="canvas" width="400" height="400" style="border: 10px;"></canvas>
      <script>
         var canvas = document.getElementById("canvas");
         var context = canvas.getContext("2d");
         var radius = canvas.height / 2;
         context.translate(radius, radius);
         radius = radius * 0.90
         Clock();

         function Clock() {
            Face(context, radius);
         }

         function Face(context, radius) {
            var gradient;
            context.beginPath();
            context.arc(0, 0, radius, 0, 2 * Math.PI);
            context.fillStyle = 'white';
            context.fill();
            gradient = context.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
            gradient.addColorStop(0, '#555555');
            gradient.addColorStop(0.5, 'lightblue');
            gradient.addColorStop(1, '#555555');
            context.strokeStyle = gradient;
            context.lineWidth = 25;
            context.stroke();
            context.closePath();
            context.beginPath();
            context.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
            context.fillStyle = '#555555';
            context.fill();
            context.closePath()
         }
      </script>
   </body>
</html>

The output returned by the code is

Adding a Face to Canvas

Adding numbers and hands

Every clock needs numbers and hands to identify the time. So, we'll number the clock area symmetrically and draw hands as we commonly see in the real mechanical clock. The implementation code is given below.

<!DOCTYPE html>
<html lang="en">
   <head>
      <title>canvas clock</title>
   </head>
   <body onload="clock();">
      <canvas id="canvas" width="400" height="400" style="border: 10px;"></canvas>
      <script>
         var canvas = document.getElementById("canvas");
         var context = canvas.getContext("2d");
         var radius = canvas.height / 2;
         context.translate(radius, radius);
         radius = radius * 0.90;
         Clock();

         function Clock() {
            Face(context, radius);
            Numbers(context, radius);
            Time(context, radius);
         }

         function Face(context, radius) {
            var gradient;
            context.beginPath();
            context.arc(0, 0, radius, 0, 2 * Math.PI);
            context.fillStyle = 'white';
            context.fill();
            gradient = context.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
            gradient.addColorStop(0, '#555555');
            gradient.addColorStop(0.5, 'lightblue');
            gradient.addColorStop(1, '#555555');
            context.strokeStyle = gradient;
            context.lineWidth = 20;
            context.stroke();
            context.closePath();
            context.beginPath();
            context.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
            context.fillStyle = '#555555';
            context.fill();
            context.closePath()
         }

         function Numbers(context, radius) {
            var angle;
            var number;
            context.font = radius * 0.15 + "px Verdana";
            context.textBaseline = "middle";
            context.textAlign = "center";
            for (number = 1; number < 13; number++) {
               angle = number * Math.PI / 6;
               context.rotate(angle);
               context.translate(0, -radius * 0.85);
               context.rotate(-angle);
               context.fillText(number.toString(), 0, 0);
               context.rotate(angle);
               context.translate(0, radius * 0.85);
               context.rotate(-angle);
            }
         }

         function Time(context, radius) {
            var Present_Time = new Date();
            var hours = Present_Time.getHours();
            var minutes = Present_Time.getMinutes();
            var seconds = Present_Time.getSeconds();
            hours = hours % 12;
            hours = (hours * Math.PI / 6) + (minutes * Math.PI / (6 * 60)) + (seconds * Math.PI / (360 * 60));
            Hands(context, hours, radius * 0.5, radius * 0.07);
            minutes = (minutes * Math.PI / 30) + (seconds * Math.PI / (30 * 60));
            Hands(context, minutes, radius * 0.8, radius * 0.07);
            seconds = (seconds * Math.PI / 30);
            Hands(context, seconds, radius * 0.9, radius * 0.02);
         }

         function Hands(context, pos, length, width) {
            context.beginPath();
            context.lineWidth = width;
            context.lineCap = "round";
            context.moveTo(0, 0);
            context.rotate(pos);
            context.lineTo(0, -length);
            context.stroke();
            context.rotate(-pos);
            context.closePath();
         }
      </script>
   </body>
</html>

The clock generated after adding numbers and hands by the above code is

Adding Numbers and Hands

Starting the clock

Till now we have built a functioning analog clock using the Canvas element, but it does not function automatically unless we refresh the HTML page every time. Hence, we will be adding another function to make the clock autonomous so we can use it to identify the time without any error.

This makes the clock automated and works without any update of time. The code for the implementation is given below.

<!DOCTYPE html>
<html lang="en">
   <head>
      <title>canvas clock</title>
   </head>
   <body onload="clock();">
      <canvas id="canvas" width="400" height="400" style="border: 10px;"></canvas>
      <script>
         var canvas = document.getElementById("canvas");
         var context = canvas.getContext("2d");
         var radius = canvas.height / 2;
         context.translate(radius, radius);
         radius = radius * 0.90;
         setInterval(Clock, 1000);

         function Clock() {
            Face(context, radius);
            Numbers(context, radius);
            Time(context, radius);
         }

         function Face(context, radius) {
            var gradient;
            context.beginPath();
            context.arc(0, 0, radius, 0, 2 * Math.PI);
            context.fillStyle = 'white';
            context.fill();
            gradient = context.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
            gradient.addColorStop(0, '#555555');
            gradient.addColorStop(0.5, 'lightblue');
            gradient.addColorStop(1, '#555555');
            context.strokeStyle = gradient;
            context.lineWidth = 20;
            context.stroke();
            context.closePath();
            context.beginPath();
            context.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
            context.fillStyle = '#555555';
            context.fill();
            context.closePath()
         }

         function Numbers(context, radius) {
            var angle;
            var number;
            context.font = radius * 0.15 + "px Verdana";
            context.textBaseline = "middle";
            context.textAlign = "center";
            for (number = 1; number < 13; number++) {
               angle = number * Math.PI / 6;
               context.rotate(angle);
               context.translate(0, -radius * 0.85);
               context.rotate(-angle);
               context.fillText(number.toString(), 0, 0);
               context.rotate(angle);
               context.translate(0, radius * 0.85);
               context.rotate(-angle);
            }
         }

         function Time(context, radius) {
            var Present_Time = new Date();
            var hours = Present_Time.getHours();
            var minutes = Present_Time.getMinutes();
            var seconds = Present_Time.getSeconds();
            hours = hours % 12;
            hours = (hours * Math.PI / 6) + (minutes * Math.PI / (6 * 60)) + (seconds * Math.PI / (360 * 60));
            Hands(context, hours, radius * 0.5, radius * 0.07);
            minutes = (minutes * Math.PI / 30) + (seconds * Math.PI / (30 * 60));
            Hands(context, minutes, radius * 0.8, radius * 0.07);
            seconds = (seconds * Math.PI / 30);
            Hands(context, seconds, radius * 0.9, radius * 0.02);
         }

         function Hands(context, pos, length, width) {
            context.beginPath();
            context.lineWidth = width;
            context.lineCap = "round";
            context.moveTo(0, 0);
            context.rotate(pos);
            context.lineTo(0, -length);
            context.stroke();
            context.rotate(-pos);
            context.closePath();
         }
      </script>
   </body>
</html>

The automatic analog clock generated by the above code is

Starting the Clock
Advertisements