This
tutorial is split in three steps:
- Step 1: Create the clock's background.
- Step 2: Initialize the current clock time.
- Step 3: Animate the clock.
Hint: This
tutorial assumes that you have a certain knowledge of HTML5 and JavaScript.
We begin
this tutorial by creating the background of this clock.
<!DOCTYPE
html>
<head>
<meta
content="text/html; charset=utf-8"
http-equiv="Content-Type" />
<title>Simple
Clock Animation</title>
<script type="application/javascript">
var canvas; // the clock
canvas
var ctx; // canvas’s
context
// clock settings
var centerX = 0;
var centerY = 0;
var radius = 150;
function init() {
canvas
= document.getElementById("clock");
ctx = canvas.getContext("2d");
centerX =
canvas.width / 2;
centerY = canvas.height / 2;
drawClock();
}
</script>
</head>
<body
onload="init()">
<canvas
id="clock" height="500" width="500">
Your browser does not support HTML5</canvas>
</body>
</html>
|
Step 1: will consist of drawing the clock. This is given by the function drawClock().
function drawClock()
{
drawClockBackground();
}
|
The function drawClockBackground() inside the drawClock() function will draw the background of the clock. It will create small lines around the center (centerX, centerY) of the clock which is also the center of the canvas.
We start creating the lines from the right to the left, and using the function drawArcAtPosition() located below. Also, we will highlight the main lines.
At final, a small circle is added at the center of the clock (see function drawLittleCircle()).
Hint: You can
also use a predefined image (if you like) instead of drawing the background of
the clock yourself.
function
drawClockBackground() {
var correction = 1/300;
var shift_unit = 1/170;
var shift_factor = 1/30;
var
angle_initial_position = 2;
var
angle_current_position_begin = 0;
var
angle_current_position_end = 0;
var repeat = 60;
var lineWidth = 10;
for (var i=0; i <
repeat; i+=1) {
angle_current_position_begin
= angle_initial_position - (i * shift_factor) - correction;
angle_current_position_end
= angle_current_position_begin + shift_unit;
if (i % 5 == 0)
lineWidth = 20;
else lineWidth = 10;
drawArcAtPosition(centerX,
centerY, radius,
angle_current_position_begin*Math.PI, angle_current_position_end*Math.PI, false, lineWidth);
}
drawLittleCircle(centerX, centerY);
}
function
drawArcAtPosition(centerX, centerY, radius,
start_angle, end_angle, counterclockwise, lineWidth) {
ctx.beginPath();
ctx.arc(centerX, centerY, radius, start_angle, end_angle, counterclockwise);
ctx.lineWidth =
lineWidth;
ctx.strokeStyle =
"black";
ctx.stroke();
ctx.closePath();
}
function
drawLittleCircle(centerX, centerY) {
drawArcAtPosition(centerX, centerY, 4, 0*Math.PI, 2*Math.PI, false, 4);
}
|
Afterward,
we create the Hands for seconds, minutes, and hours.
The below figure show the hand for the seconds.
// draw Hand for
seconds
endX = centerX + radius*Math.sin(seconds*Math.PI / 30);
endY = centerY -
radius*Math.cos(seconds*Math.PI / 30);
drawHand(centerX, centerY, endX, endY);
}
function
drawHand(beginX, beginY, endX, endY) {
ctx.beginPath();
ctx.moveTo(beginX,
beginY);
ctx.lineTo(endX,
endY);
ctx.stroke();
ctx.closePath();
}
|
The same principle is applied for minutes and hours. The hands will be a little bit smaller than that of the seconds-Hand. The minutes-Hand will move depending on the seconds-Hand, and the hours-Hand will move depending on the minutes-Hand. The moving of the Hands will be constant and smooth.
// draw Hand for
minutes
function
drawMinutesHand() {
var rotationUnit = minutes + seconds / 60; var rotationFactor = Math.PI / 30; var rotation = rotationUnit*rotationFactor; var handLength = 0.8*radius; endX = centerX + handLength*Math.sin(rotation); endY = centerY - handLength*Math.cos(rotation); drawHand(centerX, centerY, endX, endY);
}
// draw Hand for
hours
function
drawHoursHand() {
var rotationUnit = 5*hours + minutes / 12; var rotationFactor = Math.PI / 30; var rotation = rotationUnit*rotationFactor; var handLength = 0.4*radius; endX = centerX + handLength*Math.sin(rotation); endY = centerY - handLength*Math.cos(rotation); drawHand(centerX, centerY, endX, endY);
}
|
The function drawClock() will be adequately updated as follow, where we add the Hands for the clock.
function drawClock()
{
drawClockBackground();
drawSecondsHand();
drawMinutesHand();
drawHoursHand();
}
|
Step 2: will consists of animating the Hands. However, before we start we have to get the current time of the system. Thus, we create 4 additional system variables as follows:
// time settings
var date;
var hours;
var minutes;
var seconds;
|
And, we create a function called initTime(), where we initialize the data object and pass to our variables the current time of our system and clock.
// get the system
time
function initTime()
{
date = new Date();
hours =
date.getHours() % 12;
minutes = date.getMinutes();
seconds = date.getSeconds();
}
|
Now, add the initTime() function before the drawClock() function in the init() function. This is because the Hands will be drawn according to the system current time.
function init() {
…
initTime();
drawClock();
}
|
Step 3: will consist now of animating the Hands(seconds, minutes, and hours) of the clock.
We are
going now to create an animate clock function called animateClock() as
follows:
// animate clock
function
animateClock() {
clearCanvas();
refreshTime();
drawClock();
}
|
Inside this
function we have three functions named: clearCanvas(), refreshTime(),
and drawClock().
The first
function will clear the canvas for the animation. The second function is going
to refresh the current elapsed time, and the final function, which we have
already seen, is going to redraw the clock with its Hands according to the refreshed
time.
// clear canvas
function
clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
// refresh time
after 1 seconde
function
refreshTime() {
seconds += 1;
if
(Math.floor((seconds / 60)) != 0) { minutes += 1; seconds %= 60; }
if
(Math.floor((minutes / 60)) != 0) { hours += 1; minutes %= 60; }
}
// draw or redraw
Clock after time refresh
function drawClock()
{
drawClockBackground();
drawSecondsHand();
drawMinutesHand();
drawHoursHand();
}
|
In order to animate the clock we are going now to add the setInterval(..) function inside the init() function which will animate the clock every second. Of course, the function that will be called every second is the animateClock() function.
function init() {
canvas =
document.getElementById("clock");
ctx =
canvas.getContext("2d");
centerX =
canvas.width / 2;
centerY =
canvas.height / 2;
initTime();
drawClock();
setInterval("animateClock()",
1000);
}
|
The full clock's code can be viewed below:
<!DOCTYPE
html>
<head>
<meta
content="text/html; charset=utf-8"
http-equiv="Content-Type" />
<title>Simple
Clock Animation</title>
<script
type="application/javascript">
var canvas; // the
clock canvas
var ctx; // canvas's
context
// clock settings
var centerX = 0;
var centerY = 0;
var radius = 150;
// time settings
var date;
var hours;
var minutes;
var seconds;
function init() {
canvas = document.getElementById("clock");
ctx = canvas.getContext("2d");
centerX =
canvas.width / 2;
centerY = canvas.height / 2;
initTime();
drawClock();
setInterval("animateClock()",
1000);
}
// get the system
time
function initTime()
{
date = new Date();
hours
= date.getHours() % 12;
minutes
= date.getMinutes();
seconds
= date.getSeconds();
}
// animate clock
function
animateClock() {
clearCanvas();
refreshTime();
drawClock();
}
// clear canvas
function
clearCanvas() {
ctx.clearRect(0, 0,
canvas.width, canvas.height);
}
// refresh time
after 1 seconde
function
refreshTime() {
seconds += 1;
if
(Math.floor((seconds / 60)) != 0) { minutes += 1; seconds %= 60; }
if
(Math.floor((minutes / 60)) != 0) { hours += 1; minutes %= 60; }
}
// draw or redraw
Clock after time refresh
function drawClock()
{
drawClockBackground();
drawSecondsHand();
drawMinutesHand();
drawHoursHand();
}
function
drawHand(beginX, beginY, endX, endY) {
ctx.beginPath();
ctx.moveTo(beginX,
beginY);
ctx.lineTo(endX, endY);
ctx.stroke();
ctx.closePath();
}
// draw Hand for
seconds
function
drawSecondsHand() {
endX = centerX +
radius*Math.sin(seconds*Math.PI / 30);
endY = centerY -
radius*Math.cos(seconds*Math.PI / 30);
drawHand(centerX, centerY, endX, endY);
}
// draw Hand for minutes function drawMinutesHand() { var rotationUnit = minutes + seconds / 60; var rotationFactor = Math.PI / 30; var rotation = rotationUnit*rotationFactor; var handLength = 0.8*radius; endX = centerX + handLength*Math.sin(rotation); endY = centerY - handLength*Math.cos(rotation); drawHand(centerX, centerY, endX, endY); } // draw Hand for hours function drawHoursHand() { var rotationUnit = 5 * hours + minutes / 12; var rotationFactor = Math.PI / 30; var rotation = rotationUnit*rotationFactor; var handLength = 0.4*radius; endX = centerX + handLength*Math.sin(rotation); endY = centerY - handLength*Math.cos(rotation); drawHand(centerX, centerY, endX, endY); }
function
drawClockBackground() {
var correction =
1/300;
var shift_unit =
1/170;
var shift_factor =
1/30;
var angle_initial_position = 2;
var angle_current_position_begin = 0;
var angle_current_position_end = 0;
var repeat = 60;
var lineWidth = 10;
for (var i=0; i <
repeat; i+=1) {
angle_current_position_begin
= angle_initial_position - (i * shift_factor) - correction;
angle_current_position_end = angle_current_position_begin + shift_unit;
if (i % 5 == 0)
lineWidth = 20;
else lineWidth = 10;
drawArcAtPosition(centerX,
centerY, radius,
angle_current_position_begin*Math.PI, angle_current_position_end*Math.PI, false, lineWidth);
}
drawLittleCircle(centerX,
centerY);
}
function
drawArcAtPosition(centerX, centerY, radius, start_angle,
end_angle, counterclockwise, lineWidth) {
ctx.beginPath();
ctx.arc(centerX, centerY, radius, start_angle, end_angle, counterclockwise);
ctx.lineWidth =
lineWidth;
ctx.strokeStyle =
"black";
ctx.stroke();
ctx.closePath();
}
function
drawLittleCircle(centerX, centerY) {
drawArcAtPosition(centerX, centerY, 4, 0*Math.PI, 2*Math.PI, false, 4);
}
</script>
</head>
<body
onload="init()">
<canvas
id="clock" height="500" width="500">
Your browser does not support HTML5</canvas>
</body>
</html>
|
+5!
ReplyDeletecreate animation rotate view
ReplyDelete