1,canvas
- canvas is h5 a new tag added, so it may not be compatible in the lower version of ie.
- Canvas is a canvas, which can draw graphics freely.
- canvas is a native js object and jq is not recommended
2. Basic use and introduction of canvas
1. Foundation use
Use the canvas tag to add width and height attributes
The canvas tag is an inline tag
<html> <canvas height='400px' width='400px'></canvas> </html> <style> canvas{ //You can set properties such as width, height and outer margin of the border } </style>
Low version incompatibility
Add prompt
<canvas height='400px' width='400px'>This version of browser does not support canvas Label, please update your browser or use tinder</canvas>
3. canvas draw line
1, Basic drawing method of straight line
The coordinate point is the origin from the point in the upper left corner__
1. Get canvas node
2. Create canvas path context
3. Open a path
4. Path starting point
5. Path end point
6. Add color to the path
7. End path
//Fixing steps var canvas=document.getElementById('canvas') //Get canvas node var c=canvas.getContext('2d') //Establish canvas path context c.beginPath() //Enable a path beginpath() has the function of closing the previous line c.moveTo(100,100) //Path start point c.lineTo(200,200) //Path end point //Set color before shading c.strokeStyle='green' //General color properties //Set lineweight c.lineWidth=5; c.stroke() //Add color to path c.closePath() //End path //Translation center point can.translate(width / 2, height / 2)
2, Draw colorful lines and dashes
If you need to draw multiple lines with different colors, set the path, coordinate point and color for each line
//Fixing steps var canvas=document.getElementById('canvas') //Get canvas node var c=canvas.getContext('2d') //Establish canvas path context //First straight line c.beginPath() //Open a path c.moveTo(100,200) //Path start point c.lineTo(200,200) //Path end point //Set color before shading c.strokeStyle='green' //General color properties //Set lineweight c.lineWidth=5; c.stroke() //Add color to path c.closePath() //End path //Second straight line c.beginPath() //Open a path c.moveTo(200,200) //Path start point c.lineTo(200,100) //Path end point //Set color before shading c.strokeStyle='green' //General color properties //Set lineweight c.lineWidth=5; c.stroke() //Add color to path c.closePath() //End path //Third straight line c.beginPath() //Open a path c.moveTo(200,100) //Path start point c.lineTo(100,100) //Path end point //Set color before shading c.strokeStyle='green' //General color properties //Set lineweight c.lineWidth=5; c.stroke() //Add color to path c.closePath() //End path //Fourth straight line c.beginPath() //Open a path c.moveTo(100,100) //Path start point c.lineTo(100,200) //Path end point //Set color before shading c.strokeStyle='green' //General color properties //Set lineweight c.lineWidth=5; c.stroke() //Add color to path c.closePath() //End path
The repeatability of this code is too high, so we can encapsulate the code in a straight line to get the following code
//c is the canvas drawn function drawLine(x1, y1, x2, y2, color, width) { //x1: start abscissa, y1: start ordinate, x2: end abscissa, y2: end ordinate, color: line color, width: line width c.beginPath() //Open a path c.moveTo(x1, y1) //Path start point c.lineTo(x2, y2) //Path end point //Set color before shading c.strokeStyle = color //General color properties //Set lineweight c.lineWidth = width; c.stroke() //Add color to path c.closePath() //End path }
3, Straight line combination
When we need to use a uniform color line continuously, we can use the lineto() method to draw it together
//Fixing steps var canvas=document.getElementById('canvas') //Get canvas node var c=canvas.getContext('2d') //Establish canvas path context c.beginPath() //Open a path c.moveTo(100,200) //Path start point c.lineTo(200,200) c.lineTo(100,200) c.lineTo(100,100) c.lineTo(100,200) //Path end point //Set color before shading c.strokeStyle='green' //General color properties //Set lineweight c.lineWidth=5; c.stroke() //Add color to path c.closePath() //End path
4, Dotted line
The dotted line is divided by multiple lines, so we can use multiple lines to form the dotted line. We can use the line function encapsulated above
//Construct a dashed line drawLine(100,100,105,100,red,2) drawLine(110,100,115,100,red,2) drawLine(120,100,125,100,red,2) drawLine(130,100,135,100,red,2) //Or use the method directly can.setLineDash(5,15) //Parameter 1: length of each segment of dotted line, parameter 2: interval drawLine(130,100,135,100,red,2) //You can use the for loop to build dashed lines for (let i = 0; i < 20; i++) { drawLine(100 + i * 10, 100, 105 + i * 10, 100, 'red', 2) } //If you need to construct a slash, you can change the abscissa and ordinate at the same time for (let i = 0; i < 20; i++) { drawLine(100 + i * 10, 100 + i * 10, 105 + i * 10, 105 + i * 10, 'red', 2) }
4. Rectangle
We can draw a rectangle
can.rect(x,y,width,height) //Draw a rectangle /*** x : x coordinate of the upper left corner of the rectangle y : y coordinate of the upper left corner of the rectangle width: Width of rectangle height: Height of rectangle ***/ can.rect(x,y,width,height) //Fill rectangle can.fillstyle='red' can.fill() //Description border can.strokeStyle='red' //Set rectangle border color can.lineWidth=5 //Sets the width of the rectangular border can.stroke() //Set a hollow rectangle //There will be a problem that the rectangular border is covered, so we need to fill it first and stroke it. Don't reverse it //More diversified methods //Draw a filled rectangle can.fillStyle = 'red' //Rectangle fill color can.fillRect(x,y,width,height) /*** x : x coordinate of the upper left corner of the rectangle y : y coordinate of the upper left corner of the rectangle width: Width of rectangle height: Height of rectangle ***/ //Draw a hollow rectangle can.strokeStyle = 'red' //Border color can.lineWidth=5 //Sets the width of the rectangular border can.strokeRect(x,y,width,height) /*** x : x coordinate of the upper left corner of the rectangle y : y coordinate of the upper left corner of the rectangle width: Width of rectangle height: Height of rectangle ***/
Thus, we can encapsulate the rectangular function
function drawFill(x, y, width, height, color) { //Parameter 1: ordinate of rectangle, parameter 2: abscissa of rectangle, parameter 3: width of rectangle, parameter 4: height of rectangle, parameter 5: color of rectangle can.fillStyle = color can.fillRect(x, y, width, height) }
5. Draw a rectangular statistical chart with straight lines and rectangles
//Fixing steps var canvas = document.getElementById('canvas') //Get canvas node var can = canvas.getContext('2d') //Establish canvas path context //Draw axis can.beginPath() //Open a path can.moveTo(100, 100) //Path start point can.lineTo(100, 400) can.lineTo(400, 400) //Path end point //Set color before shading can.strokeStyle = 'green' //General color properties //Set lineweight can.lineWidth = 1; can.stroke() //Add color to path can.closePath() //End path function drawFill(x, y, width, height, color) { can.fillStyle = color can.fillRect(x, y, width, height) } //Add rectangle drawFill(110, 200, 30, 200, 'red') drawFill(160, 240, 30, 160, 'yellow') drawFill(210, 390, 30, 10, 'green') //This is inefficient, so we can further upgrade this function function drawFillARR(data, width = 30, mr = 20, color = 'red') { let x = 100 data.forEach(item => { can.fillStyle = color x += width + mr can.fillRect(x, 400 - item, width, item) }); } drawFillARR([100, 20, 310, 20,100]) //In this way, you only need to pass in the array in an array to draw a simple cylindrical statistical table //Randomly generated chart function drawFillRandom(width = 30, mr = 20, color = 'red') { let x = 100 let data = [] for (let i = 0; i < 6; i++) { let height = Math.random() * 280 + 10 data.push(height) } data.forEach((item, index) => { can.fillStyle = color if (index == 0) { x += mr } else { x += width + mr } can.fillRect(x, 400 - item, width, item) }); } drawFillRandom()
6. Expand knowledge
- Generate hexadecimal random color function
- Generate rgb random number
//Randomly generated hexadecimal color let color16='#' + parseInt(Math.random() * 0Xffffff).toString(16) //Randomly generate rgb color let rgbaColor = `rgb(${parseInt(Math.random() * 256)},${parseInt(Math.random() * 256)},${parseInt(Math.random() * 256)})` console.log(rgbaColor);
7. Clear canvas (important)
Method: can clearRect(x,y,width,height)
can.clearRect(x,y,width,height) /*** x : Clear the x coordinate of the upper left corner y : Clear the y coordinate of the upper left corner width: Clear width height: Clear height ***/
8. Draw a circle
Method: can arc(x,y,radius,startAngle,endAngle,counterclockwise)
can.arc(x,y,radius,startAngle,endAngle,counterclockwise) /*** x: x-axis coordinates of the center point of the circle y: y-axis coordinates of the center point of the circle radius: Radius of circle startAngle: Starting angle endAngle: End angle math PI is 180 degrees. Changing this value can draw an arc counterclockwise: true is counterclockwise and false is clockwise ***/ can.arc(250,250,200,0,Math.PI*2,false) //Draw a circle can.fillStyle = 'green' //Fill set color can.fill() //fill color can.lineWidth=5 //Line width of circle can.strokeStyle='red' //Line set color can.stroke() //Add color to lines Calculate circumferential coordinates x=x+r*cos(angle) Abscissa y=y+r*sin(angle) Ordinate
Simple practice
Draw a teacup
<body> <canvas id="canvas" height="600" width="600"></canvas> </body> <script> //Fixing steps var canvas = document.getElementById('canvas') //Get canvas node var can = canvas.getContext('2d') //Establish canvas path context //teacup can.rect(200, 300, 200, 200) can.lineWidth = 4 can.stroke() can.beginPath() can.arc(400, 400, 50, Math.PI / 2, Math.PI * 2 * 3 / 4, true) can.lineWidth = 10 can.stroke() //breath can.beginPath() can.arc(400, 400, 50, Math.PI / 2, Math.PI * 2 * 3 / 4, true) can.lineWidth = 10 can.stroke() for (let i = 0; i < 4; i++) { can.beginPath() can.arc(230 + i * 40, 200, 20, Math.PI / 2, Math.PI * 2 * 3 / 4, false) can.lineWidth = 2 can.stroke() can.beginPath() can.arc(230 + i * 40, 240, 20, Math.PI / 2, Math.PI * 2 * 3 / 4, true) can.lineWidth = 2 can.stroke() } </script>
9. Expand knowledge
Use the timer to draw the statistical timer
<body> <canvas id="canvas" height="500" width="500"></canvas> </body> <script> //Fixing steps var canvas = document.getElementById('canvas') //Get canvas node var can = canvas.getContext('2d') //Establish canvas path context let deg = Math.PI / 180 let count = 0 let timer = setInterval( function () { if (count > 360) { clearInterval(timer) } count++ can.beginPath() can.arc(250, 250, 200, 0, count * deg, false) //Draw a circle // can.fillStyle = 'green' / / fill setting color // can.fill() / / fill color // can.lineWidth = 5 / / line width of the circle can.strokeStyle = 'red' //Line set color can.stroke() //Add color to lines }, 1 ) </script>
10. Collision detection
The logic is: if it collides with the specified position, the acceleration is opposite
<body> <canvas id="canvas" height="500" width="500"></canvas> </body> <script> //Fixing steps var canvas = document.getElementById('canvas') //Get canvas node var can = canvas.getContext('2d') //Establish canvas path context let arc1 = { x: 20, y: 20, r: 20, xv: 1, yv: 1 } let width = 500 let height = 500 setInterval(function () { can.clearRect(0, 0, width, height) //Empty the canvas after each movement can.beginPath() //Clear the brush when the motion is complete if ((arc1.x - arc1.r) < 0 || (arc1.x + arc1.r) >= width) { //Making elastic collision of x-axis arc1.xv = -arc1.xv } arc1.x += arc1.xv if ((arc1.y - arc1.r) < 0 || (arc1.y + arc1.r) >= height) { //Making elastic collision of y-axis arc1.yv = -arc1.yv } arc1.y += arc1.yv can.arc(arc1.x, arc1.y, arc1.r, 0, Math.PI * 2, false) //Draw a ball can.fillStyle = 'green' //Fill set color can.fill() //fill color }, 5) </script>
Object oriented small ball, randomly generate multiple small balls
Randomly generate multiple small ball collisions <body> <canvas id="canvas" height="500" width="500"></canvas> </body> <script> //Fixing steps var canvas = document.getElementById('canvas') //Get canvas node var can = canvas.getContext('2d') //Establish canvas path context let width = 500 let height = 500 function r(num) { return parseInt(Math.random() * num) } function Ball() { //Randomly generated ball this.r = r(40) + 10 //Small ball radius [10,50) //Randomly generated location this.x = r(400) + 50 this.y = r(400) + 50 this.color = '#' + parseInt(Math.random() * 0Xffffff).toString(16) / / randomly generate color this.xv = r(3) > 1 ? ~(r(2) + 2) : r(2) + 2//[2,5) this.yv = r(3) > 1 ? ~(r(2) + 2) : r(2) + 2//[2,5) } Ball.prototype.show = function () { this.run() can.beginPath() //Clear the brush when the motion is complete can.arc(this.x, this.y, this.r, 0, Math.PI * 2, false) //Draw a ball can.fillStyle = this.color//Fill set color can.fill() //fill color } Ball.prototype.run = function () { // can.clearRect(0, 0, width, height) / / empty the canvas after each movement if ((this.x - this.r) < 0 || (this.x + this.r) >= width) { //Making elastic collision of x-axis this.xv = -this.xv } this.x += this.xv if ((this.y - this.r) < 0 || (this.y + this.r) >= height) { //Making elastic collision of y-axis this.yv = -this.yv } this.y += this.yv } let timer = null function addBall(num) { can.clearRect(0, 0, width, height) if (timer) { clearInterval(timer) } let ballArr = [] for (let i = 0; i < num; i++) { // Add ball let ball = new Ball() ballArr.push(ball) ball.show() } timer = setInterval(function () { //Start moving can.clearRect(0, 0, width, height) //Empty the canvas after each movement for (let i = 0; i < ballArr.length; i++) { ballArr[i].show() } }, 5) } addBall(10) </script>
11. Draw text
Method: can fillText(text,x,y,maxWidth)
//Draw basic text can.fillText(text,x,y,maxWidth) /*** text: Text content x: x coordinate of the lower left corner of the text y: y coordinate of the lower left corner of the text maxWidth:If the maximum width of the optional text is specified, it will overflow ***/ //Set text style can.font='30px Microsoft YaHei ' //Size and style can.fillstyle='red' //Set text color can.fillText('Hello',300,300) //Properties of horizontal text textAlign Value of:start end left right center The default value is left can.textAlign='left' //Alignment of baseline (vertical position) textBaseline: Top Botton Middle The default value is top can.textBaseline='top' //Draw empty text can.strokeStyle='green' can.strokeText('Hello',200,200) //It doesn't matter. All students learn by themselves //Draw Gradient Text can.createLinearGradient(0,0,canvas,width,0)
12. Draw picture
Syntax 1:
can.drawImage(img,x,y)
can.drawImage(img,x,y) /*** img:picture x: x-axis coordinates of the starting position of the picture y: y-axis coordinates of the starting position of the picture ***/
Syntax 2:
can.drawImage(img,x,y,width,height)
can.drawImage(img,x,y,width,height) /*** img:picture x: x-axis coordinates of the starting position of the picture y: y-axis coordinates of the starting position of the picture width:Picture width (zoom in or out) height:The height of the cut picture (zoom in or out) ***/
Grammar 3
can.drawImage(img,sx,sy,swidth,sheight,x,y,width,height)
can.drawImage(img,sx,sy,swidth,sheight,x,y,width,height) /*** img:picture sx:The x-axis coordinate of the start of cutting sy:y-axis coordinates of the start of cutting swidth:Width of the picture to start cutting sheight:Height of the picture to start cutting x: x-axis coordinates of the position after image cutting y: y-axis coordinates of the position after image cutting width:Width after image cutting height:Height after image cutting ***/
Picture knowledge supplement
let img = new Image() //Create an instance of a picture img.src = 'fangzi.jpg' //set up path /*** The function will be triggered when the picture is loaded onload triggered successfully: Failed to trigger onerror: ***/
var canvas = document.getElementById('canvas') //Get canvas node var can = canvas.getContext('2d') //Establish canvas path context let img = new Image() img.src = 'fangzi.jpg' img.onload = function () { console.log(img.width, img.height); can.drawImage(img, 450, 400, 460, 500, 0, 0, 250, 250) //Cut and move to a location }
getImageData(x,y,width,height)
//Gets the pixel data of the rectangle at the specified position can.getImageData(x,y,width,height) /*** x: Position x-axis coordinates y: Position y-axis coordinates width:image width height:Picture height ***/ //After obtaining, it is stored in the form of an array If you use local pictures, there will be cross domain problems, and there is no solution add to img.crossOrigin = ''; Use web pictures
putImageData(imaData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight)
//Place the picture in a position putImageData(imaData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight) /*** imgData //Specifies the imageData object to put back on the canvas x ImageData The x-axis coordinate of the upper left corner of the object, calculated in pixels y ImageData The y-axis coordinate of the upper left corner of the object, calculated in pixels dirtyX Optional parameter, horizontal x, calculated in pixels, where the image is placed on the canvas dirtyy Optional parameter, horizontal value, calculated in pixels, where the image is placed on the canvas dirtyWidth Optional, the width of the drawn image dirtyHeight Optional, the height at which the image is drawn on the canvas ***/ //You can first use getImageData to get the data to be placed in putImageData
The previous summary strengthens the practice of linear ball
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ margin: 0; padding: 0; } /* canvas { border: 1px solid; display: block; margin: 0 auto; } */ </style> </head> <body style="overflow:-Scroll;overflow-y:hidden"> <canvas id="canvas"></canvas> </body> <script> let canvas = document.querySelector('#canvas') let can = canvas.getContext('2d') let height = document.documentElement.clientHeight let width = document.documentElement.clientWidth canvas.height = height canvas.width = width // let width = 800 // let height = 800 //Draw a straight line function drawLine(x1, y1, x2, y2, color) { //x1: start abscissa, y1: start ordinate, x2: end abscissa, y2: end ordinate, color: line color, width: line width can.beginPath() //Open a path can.moveTo(x1, y1) //Path start point can.lineTo(x2, y2) //Path end point //Set color before shading can.strokeStyle = color || '#000 '/ / general color attribute //Set lineweight can.lineWidth = 2; can.stroke() //Add color to path can.closePath() //End path } //Write text function drawText(text, x, y) { can.font = '15px Microsoft YaHei ' //Size and style can.textAlign = 'center' can.textBaseline = 'top' can.fillText(text, x, y) } let strArr = 'python java javasprit HTML5 CSS3 Nodejs PHP VUE React'.split(' ') //Generate small ball function r(num) { return parseInt(Math.random() * num) } function Ball() { //Randomly generated ball this.r = r(40) + 10 //Small ball radius [10,50) //Randomly generated location this.x = r(width - 100) + 50 this.y = r(height - 100) + 50 this.color = `rgb(${parseInt(Math.random() * 256)},${parseInt(Math.random() * 256)},${parseInt(Math.random() * 256)})` //Randomly generated color this.xv = r(3) > 1 ? ~(r(2) + 2) : r(2) + 2//[2,5) this.yv = r(3) > 1 ? ~(r(2) + 2) : r(2) + 2//[2,5) } Ball.prototype.show = function () { this.run() can.beginPath() //Clear the brush when the motion is complete can.arc(this.x, this.y, this.r, 0, Math.PI * 2, false) //Draw a ball can.fillStyle = this.color//Fill set color can.fill() //fill color } Ball.prototype.run = function () { // can.clearRect(0, 0, width, height) / / empty the canvas after each movement if ((this.x - this.r) < 0 || (this.x + this.r) >= width) { //Making elastic collision of x-axis this.xv = -this.xv } this.x += this.xv if ((this.y - this.r) < 0 || (this.y + this.r) >= height) { //Making elastic collision of y-axis this.yv = -this.yv } this.y += this.yv } let timer = null function addBall(num) { can.clearRect(0, 0, width, height) if (timer) { clearInterval(timer) } let ballArr = [] for (let i = 0; i < num; i++) { // Add ball let ball = new Ball() ballArr.push(ball) ball.show() } timer = setInterval(function () { //Start moving can.clearRect(0, 0, width, height) //Empty the canvas after each movement for (let i = 0; i < ballArr.length; i++) { ballArr[i].show() drawText(strArr[i], ballArr[i].x, ballArr[i].y + ballArr[i].r + 5) //Add text tracking ball for (let j = 0; j < i; j++) { drawLine(ballArr[i].x, ballArr[i].y, ballArr[j].x, ballArr[j].y, ballArr[i].color) //Dash from large to small } } }, 10) } addBall(strArr.length) </script> </html>
Strengthen linear practice
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } /* canvas { border: 1px solid; display: block; margin: 0 auto; } */ </style> </head> <body style="overflow:-Scroll;overflow-y:hidden"> <canvas id="canvas"></canvas> </body> <script> let canvas = document.querySelector('#canvas') let body = document.querySelector('body') let can = canvas.getContext('2d') let height = document.documentElement.clientHeight let width = document.documentElement.clientWidth canvas.height = height canvas.width = width //Generate small ball function r(num) { return parseInt(Math.random() * num) } function Ball(x, y) { //Randomly generated ball this.r = 60 //Small ball radius [10,50) //Randomly generated location this.x = x this.y = y this.color = `rgb(${parseInt(Math.random() * 256)},${parseInt(Math.random() * 256)},${parseInt(Math.random() * 256)})` //Randomly generated color } Ball.prototype.show = function () { can.beginPath() this.r -= 5 //Clear the brush when the motion is complete can.arc(this.x, this.y, this.r, 0, Math.PI * 2, false) //Draw a ball can.fillStyle = this.color//Fill set color can.fill() //fill color } let ballArr = [] setInterval(function () { //Remove the ball from the array can.clearRect(0, 0, width, height) for (let i = 0; i < ballArr.length; i++) { let ball = ballArr[i] if (ball.r <= 0) { //When the radius is 0, this element is removed from the array ballArr.splice(i, 1) } else { ballArr[i].show() //Otherwise, continue rendering } } }, 30) window.addEventListener('mousemove', function (e) { //Get x, y when moving let ball = new Ball(e.x, e.y) ballArr.push(ball) ball.show() }) </script> </html>
Draw clock
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } div { background-color: #ccc; border-radius: 20px; width: 400px; height: 400px; margin: 0 auto; margin-top: 100px; } canvas { /* border: 1px solid; */ /* background-color: #fff; */ display: block; margin: 0 auto; } </style> </head> <body style="overflow:-Scroll;overflow-y:hidden"> <div> <canvas id="canvas"></canvas> </div> </body> <script> let canvas = document.querySelector('#canvas') let can = canvas.getContext('2d') // let height = document.documentElement.clientHeight // let width = document.documentElement.clientWidth // canvas.height = height // canvas.width = width // let width = 800 // let height = 800 canvas.height = 400 canvas.width = 400 let height = width = 400 //Clock width and height let x = y = 200 //Clock center point let r = 180 //Clock radius let r_houe = 60 //Hour hand length let r_min = 120 //Minute hand length let r_s = 140 //Second hand length let r_text = 140 //Text radius let r_square = 165 //Scale radius let r_circle = 10 //Dial dot let deg = 2 * Math.PI //Define basic circle size //Draw a straight line function drawLine(x1, y1, x2, y2, color, width) { //x1: start abscissa, y1: start ordinate, x2: end abscissa, y2: end ordinate, color: line color, width: line width can.beginPath() //Open a path can.moveTo(x1, y1) //Path start point can.lineTo(x2, y2) //Path end point //Set color before shading can.strokeStyle = color || '#000 '/ / general color attribute //Set lineweight can.lineWidth = width || 2; can.stroke() //Add color to path can.closePath() //End path } //Draw text function drawText(text, x, y) { can.font = '700 20px Microsoft YaHei ' //Size and style can.textAlign = 'center' can.textBaseline = 'middle' can.fillText(text, x, y) } //Draw a circle function drawArc(x, y, r, color) { can.beginPath() can.arc(x, y, r, 0, Math.PI * 2, false) // can.lineWidth = 1 // can.stroke() can.fillStyle = color || '#fff' can.fill() } // 1. Reset center point can.translate(width / 2, height / 2) function startM() { //Constant value //2. Draw dial drawArc(0, 0, r) //Clock dial drawArc(0, 0, r_circle, '#000 ') / / center point //3. Draw numbers for (let i = 1; i <= 12; i++) { let flagDeg = (2 * Math.PI) / 12 * i + (2 * Math.PI) / 12 * (~2) x = r_text * Math.cos(flagDeg) y = r_text * Math.sin(flagDeg) drawText(i, x, y) } //4. Draw scale for (let i = 1; i <= 60; i++) { let flagDeg = (2 * Math.PI) / 60 * i if (i % 5 == 0) { drawLine(r * Math.cos(flagDeg), r * Math.sin(flagDeg), (r - 10) * Math.cos(flagDeg), (r - 10) * Math.sin(flagDeg), '#aaa', 2) } else { drawLine(r * Math.cos(flagDeg), r * Math.sin(flagDeg), (r - 6) * Math.cos(flagDeg), (r - 6) * Math.sin(flagDeg), '#ccc', 1) } } } startM() drawLine(0, 0, 0, ~r_houe, 'red', 5) //Clock drawLine(0, 0, 0, ~r_min, 'yellow', 3) //minute hand drawLine(0, 0, 0, ~r_s, 'blue', 2) //second hand function houe() { this.x = 0 this.y = r_houe this.r = r_houe this.color = 'red' this.width = 5 this.total = 0 } function min() { this.x = 0 this.y = r_min this.r = r_min this.color = 'blue' this.width = 3 this.total = 0 } function mis() { this.x = 0 this.y = r_s this.r = r_s this.color = 'yellow' this.width = 2 this.total = 0 } houe.prototype.run = function (m) { let flagDeg = (2 * Math.PI) / 12 * this.total - Math.PI / 2 + m drawLine(0, 0, this.r * Math.cos(flagDeg), this.r * Math.sin(flagDeg), this.color, this.width) //Clock } min.prototype.run = function (s) { let flagDeg = (2 * Math.PI) / 60 * this.total - Math.PI / 2 + s drawLine(0, 0, this.r * Math.cos(flagDeg), this.r * Math.sin(flagDeg), this.color, this.width) //minute hand } mis.prototype.run = function () { let flagDeg = (2 * Math.PI) / 60 * this.total - Math.PI / 2 drawLine(0, 0, this.r * Math.cos(flagDeg), this.r * Math.sin(flagDeg), this.color, this.width) //second hand } let h = new houe() let m = new min() let s = new mis() setInterval(function () { can.clearRect(-200, -200, 400, 400) startM() if (s.total == 60) { s.total = 0 s.total += 1 if (m.total == 60) { m.total = 0 m.total += 1 if (h.total == 12) { h.total = 0 m.total += 1 } else { h.total += 1 } } else { m.total += 1 } } else { s.total += 1 } h.run((2 * Math.PI / 60 * m.total) / 360 * 30) m.run((2 * Math.PI / 60 * s.total) / 360 * 6) s.run() }, 1000) </script> </html>