English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Reading this article requires some basic knowledge of canvas usage. This article shares HTML5 Simple Tutorial on Implementing Circular Clock with Canvas
Step 1:Create a simple HTML file and define the element canvas in the <body> tag.
canvas.html
<html> <head> <title>Canvas clock tutorial</title> </head> <body> <canvas id="clock" width="400" height="400"></canvas> </body> </html>
After this step is completed, open canvas.html with the browser, and you will find nothing. This is because we have not drawn anything on the canvas and have not defined its boundaries.
Add CSS style attributes to <canvas> in canvas.html.
<html> <head> <title>Canvas clock tutorial</title> <style type="text/css"> canvas { border: 1px solid black; } </style> </head> <body> <canvas id="clock" width="400" height="400"></canvas> </body> </html>
This way, we can see the outline of the <canvas>.
When the width and height are not set, canvas will initialize the width to300 pixels and height of150 pixels. This element can be defined in size with CSS, but the image will stretch to fit its frame size: if the CSS size is not consistent with the initial canvas ratio, it will appear distorted.
Note: If the image you draw is distorted, try to specify the width and height in the <canvas> attributes explicitly, rather than using CSS.
Step 2: Create a new draw.js file to implement the logic of drawing a circular clock and perform initialization work.
Undoubtedly, to implement a clock, you need to get the system time.
In JavaScript syntax, you can use Date() to get the current time in real time.
var currentTime = new Date();
What needs to be mastered next is the function to draw a circle in canvas.
The method arc(x, y, radius, startAngle, endAngle, anticlockwise) represents drawing an arc (circle) with (x, y) as the center and radius as the radius, starting from startAngle and ending at endAngle, and generating in the direction specified by anticlockwise (default is clockwise, true).
radians.2Among them, the units of stratAngle and endAngle are not the angle units we are familiar with, but radian units. A complete circle spans
π.2In the coordinate system of canvas, the direction of the positive x-axis is 0 radians. The clock hands rotate clockwise, with-1/2)*π is a cycle, so as shown in the figure below, the clock hands, start from (
π starts to move.
//To calculate the arc of the current time, the following method is used:12divisions, for12The modulo operation is because Date().getHours will return24hours in the 12-hour system. hour = (currentTime.getHours() % 12 ) * (2 * Math.PI /12); //MINUTE completes a circle60 divisions minute = (currentTime.getMinutes) * (2* Math.PI / 60); //SECOND completes a circle60 divisions second = (currentTime.getSeconds) * (2 * Math.PI / 60);
Since the clock circle in canvas starts from (-1/2)*π starts to move, so we also need to add (-1/2)*The starting offset of π.
We get draw.js initially:
function draw() { //The preliminary work of canvas painting var canvas = document.getElementById('clock'); var currentTime = new Date(); var hour = (currentTime.getHours()12) * Math.PI/6; var minute = currentTime.getMinutes() * Math.PI/30; var second = currentTime.getSeconds() * Math.PI/30; hour = hour - Math.PI * (1/2); minute = minute - Math.PI * (1/2); second = second - Math.PI * (1/2); if (canvas.getContext){ var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.arc(200,200,50,Math.PI*(-1/2,hour,false); ctx.moveTo(200,100); ctx.arc(200,200,100,Math.PI*(-1/2,minute,false); ctx.moveTo(200,50); ctx.arc(200,200,150,Math.PI*(-1/2,second,false); ctx.stroke(); } }
At the same time, add the reference to draw.js in canvas.html.
<html> <head> <title>Canvas clock tutorial</title> <style type="text/css"> canvas { border: 1px solid black; } </style> <script src="draw.js" type="text/javascript><}}/script> </head> <body onload="draw();"> <canvas id="clock" width="400" height="400"></canvas> </body> </html>
After completing the second step, we can see the outline of the circular clock of the current time. So, the next step is to make it move!
Step 3:Use the requestAnimationFrame() method to make the clock move.
The execution frequency of requestAnimationFrame() is1second60 frames, the user can define an event in requestAnimationFrame() so that it repeats and iterates the corresponding event in each frame.
In our case, the task that requestAnimationFrame() needs to do in each frame is very simple, that is, to add increments to the three parameters (hour hand, minute hand, second hand) of the current time, and then redraw the clock.
According to one second60 frames' frequency, then second in1the increment in one frame is:2*π / 60 / 60 = π / 1800;
the increment of minute in one frame is the increment of second's60 part; the increment of hour in one frame is the increment of minute's12part1.
Additionally, when any of the variables hour, minute, or second reaches3/2*π, it means that a cycle has been completed, and it should be re-initialized to (-1/2)*π, otherwise it will be drawn as a circle.
The update process of hour, minute, and second in the requestAnimationFrame() function is as follows:
var s = Math.PI / 1800; var m = s / 60; var h = m / 12; second = second + s; minute = minute + m; hour = hour + h; if (second >= Math.PI * (3/2)) { second = Math.PI * (-1/2); } if (minute >= Math.PI * (3/2)) { minute = Math.PI * (-1/2); } if (second >= Math.PI * (3/2)) { second = Math.PI * (-1/2); }<//span>
The complete code of draw.js is updated as follows:
function draw() { var canvas = document.getElementById('clock'); var currentTime = new Date(); var hour = (currentTime.getHours()12) * Math.PI/6; var minute = currentTime.getMinutes() * Math.PI/30; var second = currentTime.getSeconds() * Math.PI/30; hour = hour - Math.PI * (1/2); minute = minute - Math.PI * (1/2); second = second - Math.PI * (1/2); if (canvas.getContext){ var ctx = canvas.getContext('2d'); var s = Math.PI / 1800; var m = s / 60; var h = m / 12; var rotate = requestAnimationFrame(step); function step() { second = second + s; minute = minute + m; hour = hour + h; if (second >= Math.PI * (3/2)) { second = Math.PI * (-1/2); } if (minute >= Math.PI * (3/2)) { minute = Math.PI * (-1/2); } if (second >= Math.PI * (3/2)) { second = Math.PI * (-1/2); } ctx.clearRect(0, 0, 400 , 400); ctx.beginPath(); ctx.arc(200,200,50,Math.PI*(-1/2,hour,false); ctx.moveTo(200,100); ctx.arc(200,200,100,Math.PI*(-1/2,minute,false); ctx.moveTo(200,50); ctx.arc(200,200,150,Math.PI*(-1/2,second,false); ctx.stroke(); requestAnimationFrame(step); } } }
So far, we have obtained a moving circular clock, and next, we will add pointers to it.
Step 4*:Add the hour hand, minute hand, and second hand.
JS provides Math.cos() and Math.sin() to calculate the position of the pointer, and the units of the parameters they receive are also radians.
function draw() { var canvas = document.getElementById('clock'); var currentTime = new Date(); var hour = (currentTime.getHours()12) * Math.PI/6; var minute = currentTime.getMinutes() * Math.PI/30; var second = currentTime.getSeconds() * Math.PI/30; hour = hour - Math.PI * (1/2); minute = minute - Math.PI * (1/2); second = second - Math.PI * (1/2); if (canvas.getContext){ var ctx = canvas.getContext('2d'); var s = Math.PI / 1800; var m = s / 60; var h = m / 12; var rotate = requestAnimationFrame(step); function step() { second = second + s; minute = minute + m; hour = hour + h; if (second >= Math.PI * (3/2)) { second = Math.PI * (-1/2); } if (minute >= Math.PI * (3/2)) { minute = Math.PI * (-1/2); } if (second >= Math.PI * (3/2)) { second = Math.PI * (-1/2); } //The end point of the second hand xs = 150 * Math.cos(second) + 200; ys = 150 * Math.sin(second) + 200; //The end point of the minute hand xm = 100 * Math.cos(minute) + 200; ym = 100 * Math.sin(minute) + 200; //The end point of the hour hand xh = 50 * Math.cos(hour) + 200; yh = 50 * Math.sin(hour) + 200; ctx.clearRect(0, 0, 400 , 400); ctx.beginPath(); //Draw the pointer ctx.moveTo(200,200); ctx.lineTo(xs,ys); ctx.moveTo(200,200); ctx.lineTo(xm,ym); ctx.moveTo(200,200); ctx.lineTo(xh,yh); //Draw the outline of the circle ctx.moveTo(200,150); ctx.arc(200,200,50,Math.PI*(-1/2,hour,false); ctx.moveTo(200,100); ctx.arc(200,200,100,Math.PI*(-1/2,minute,false); ctx.moveTo(200,50); ctx.arc(200,200,150,Math.PI*(-1/2,second,false); ctx.stroke(); requestAnimationFrame(step); } } }
Um, although the pointers have been drawn, I feel a bit regretful because they look ugly. From an aesthetic point of view, a clock with pointers should be a full circle outline. I don't know if readers have the same feeling. I decided to backtrack step 4 in step 5.
Step 5:Personalize, beautify, and customize your clock.
html5The canvas canvas provides various style properties, such as line color, line thickness, etc.
To improve the reusability of the code, we abstract the code for drawing circles into a function.
function draw() { var canvas = document.getElementById('clock'); var currentTime = new Date(); var hour = (currentTime.getHours()12) * Math.PI/6; var minute = currentTime.getMinutes() * Math.PI/30; var second = currentTime.getSeconds() * Math.PI/30; hour = hour - Math.PI * (1/2); minute = minute - Math.PI * (1/2); second = second - Math.PI * (1/2); if (canvas.getContext){ var ctx = canvas.getContext('2d'); var s = Math.PI / 1800; var m = s / 60; var h = m / 12; var rotate = requestAnimationFrame(step); function step() { second = second + s; minute = minute + m; hour = hour + h; if (second >= Math.PI * (3/2)) { second = Math.PI * (-1/2); } if (minute >= Math.PI * (3/2)) { minute = Math.PI * (-1/2); } if (second >= Math.PI * (3/2)) { second = Math.PI * (-1/2); } ctx.clearRect(0, 0, 400 , 400); ctx.beginPath(); //Draw the outline of the circle drawCircle(ctx, 100, hour, '#99ff00'); drawCircle(ctx, 120, minute, '#99ff66); drawCircle(ctx, 140, second, '#66cc66); requestAnimationFrame(step); } } } function drawCircle(ctx, radius ,endAngle, color){ ctx.beginPath(); ctx.moveTo(200,200-radius); ctx.strokeStyle = color; ctx.lineWidth = 20; ctx.arc(200,200,radius,Math.PI*(-1/2),endAngle,false); ctx.stroke(); }
Step 6 (added later):Add digital indices to the clock.
The specific method is to add an additional canvas element, canvas. Since we can already get the time from Date(), the source of the displayed values is not a problem. The only thing readers need to know is to use the setInterval(thingstodo(),interval) method to update the index every second.
Modified canvas.html
<html> <head> <title>Canvas clock tutorial</title> <style type="text/css"> canvas { border: 1px solid black; } #display {position: absolute; top:8; left:8;} </style> <script src="draw.js" type="text/javascript><}}/script> </head> <body onload="draw();"> <canvas id="clock" width="400" height="400"></canvas> <canvas id="display" width="400" height="400"></canvas> </body> </html>
Modified draw.js
function draw() { var canvas = document.getElementById('clock'); var displayCanvas = document.getElementById('display'); var currentTime = new Date(); var hour = (currentTime.getHours()12) * Math.PI/6; var minute = currentTime.getMinutes() * Math.PI/30; var second = currentTime.getSeconds() * Math.PI/30; hour = hour - Math.PI * (1/2); minute = minute - Math.PI * (1/2); second = second - Math.PI * (1/2); if (canvas.getContext){ var ctx = canvas.getContext('2d'); var ctxD = displayCanvas.getContext('2d'); showDisplay(ctxD, currentTime); var s = Math.PI / 1800; var m = s / 60; var h = m / 12; var rotate = requestAnimationFrame(step); function step() { second = second + s; minute = minute + m; hour = hour + h; if (second >= Math.PI * (3/2)) { second = Math.PI * (-1/2); } if (minute >= Math.PI * (3/2)) { minute = Math.PI * (-1/2); } if (second >= Math.PI * (3/2)) { second = Math.PI * (-1/2); } ctx.clearRect(0, 0, 400 , 400); ctx.beginPath(); //Draw the outline of the circle drawCircle(ctx, 100, hour, '#99ff00'); drawCircle(ctx, 120, minute, '#99ff66); drawCircle(ctx, 140, second, '#66cc66); requestAnimationFrame(step); } } } function drawCircle(ctx, radius ,endAngle, color){ ctx.beginPath(); ctx.moveTo(200,200-radius); ctx.strokeStyle = color; ctx.lineWidth = 20; ctx.arc(200,200,radius,Math.PI*(-1/2),endAngle,false); ctx.stroke(); } function showDisplay(ctx, date){ var h = date.getHours(),m = date.getMinutes(),s = date.getSeconds(); //Timing Text Style ctx.font = "13px Sans-Serif ctx.textAlign = "center"; ctx.strokeText(h+:"+m+:"+s,200,200); var timmer = setInterval(function(){ s++; if(s>=60){ m++; s=0; } if(m>=60){ h++; m=0; } if(h>=24{ h=0; } ctx.clearRect(0,0,400,400); ctx.strokeText(h+:"+m+:"+s,200,200); },1000); }
The final result diagram is as follows:
That's all for this article. Hope it will be helpful to everyone's learning and also hope everyone will support the呐喊 tutorial more.
Statement: The content of this article is from the Internet, the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, does not edit manually, and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (Please replace # with @ when sending an email for reporting, and provide relevant evidence. Once verified, this site will immediately delete the content suspected of infringement.)