(四) JavaScript-Canvas-自由运动的球
JavaScript 是前端核心, 掌握这门语言是步入前端高手行列必经之路,噢,别忘了还有TypeScript, 学习它还需要OOP知识, 底层的浏览器原理、HTTP协议也必不可少, 此系列文章记录使用JavaScript和Canvas进行游戏开发, 有游戏才有趣!!!
效果图
(四) JavaScript-Canvas-自由运动的球
本节将使用window.requestAnimationFrame()函数制作动画,先从简单的开始, 理解以下内容需要对JavaScript 中的函数和class有基本的了解
本节JavaScript 技术要点
- 使用class定义类
- 使用constructor定义构造函数
- 使用Canvas Context的 arc函数绘制圆
- 动画关键函数 window.requestAnimationFrame()
1. 准备HTML页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <!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> *{padding: 0; margin: 0;} #canvas { width: 100%; height: 100%; position: absolute; top: 0; left: 0; } </style> </head> <body> <canvas id="canvas"></canvas> <script>
const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') canvas.width = window.innerWidth canvas.height = window.innerHeight </script> </body> </html>
|
2. 创建一个圆类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| <!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> *{padding: 0; margin: 0;} #canvas { width: 100%; height: 100%; position: absolute; top: 0; left: 0; } </style> </head> <body> <canvas id="canvas"></canvas> <script> const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') canvas.width = window.innerWidth canvas.height = window.innerHeight class Circle { constructor(x, y, dx, dy, radius) { this.x = x this.y = y this.dx = dx this.dy = dy this.radius = radius } } </script> </body> </html>
|
3. 定义绘制圆的函数,在Circle类中定义
- 绘制开始 beginPath()
- 绘制圆的arc函数 ctx.arc(this.x, this.y, this.radius, 0, 2*Math.PI, false)
- this.x,this.y是指当前对象的坐标
- this.radius是指当前对象的半径
- 0 表示开始角度
- 2*Math.PI 表示360度
- 最后个参数表示是否是逆时针方向绘制,设置为true或false均可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| <!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> *{padding: 0; margin: 0;} #canvas { width: 100%; height: 100%; position: absolute; top: 0; left: 0; } </style> </head> <body> <canvas id="canvas"></canvas> <script> const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') canvas.width = window.innerWidth canvas.height = window.innerHeight class Circle { constructor(x, y, dx, dy, radius) { this.x = x this.y = y this.dx = dx this.dy = dy this.radius = radius } draw() { ctx.beginPath() ctx.arc(this.x,this.y,this.radius,0,2*Math.PI, false) ctx.strokeStyle = 'blue' ctx.stroke() ctx.fill() } } </script> </body> </html>
|
4. 圆位置变化
- 圆在Canvas中位置要不断的变化才能有动画效果,所以x和y坐标不是固定的,而是动态变化的,可以定义一个数不断的更新圆的x,y的值
- 圆的位置不能超过Canvas的宽度和高度, 判断时需要将半径也算上
- 增加的函数命名为update
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| <!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> *{padding: 0; margin: 0;} #canvas { width: 100%; height: 100%; position: absolute; top: 0; left: 0; } </style> </head> <body> <canvas id="canvas"></canvas> <script> const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') canvas.width = window.innerWidth canvas.height = window.innerHeight class Circle { constructor(x, y, dx, dy, radius) { this.x = x this.y = y this.dx = dx this.dy = dy this.radius = radius } draw() { ctx.beginPath() ctx.arc(this.x,this.y,this.radius,0,2*Math.PI, false) ctx.strokeStyle = 'blue' ctx.stroke() ctx.fill() } update() { if(this.x + this.radius > canvas.width || this.x-this.radius < 0){ this.dx = -this.dx } if(this.y+this.radius > canvas.height || this.y-this.radius < 0) { this.dy = -this.dy } this.x += this.dx this.y += this.dy this.draw() } var circle = new Circle(200,200,3,3,30) circle.update() } </script> </body> </html>
|
效果如图,圆不会动,原因是update函数需要不断调用,此时只调用了一次
5. 动画
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| <!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> *{padding: 0; margin: 0;} #canvas { width: 100%; height: 100%; position: absolute; top: 0; left: 0; } </style> </head> <body> <canvas id="canvas"></canvas> <script> const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') canvas.width = window.innerWidth canvas.height = window.innerHeight class Circle { constructor(x, y, dx, dy, radius) { this.x = x this.y = y this.dx = dx this.dy = dy this.radius = radius } draw() { ctx.beginPath() ctx.arc(this.x,this.y,this.radius,0,2*Math.PI, false) ctx.strokeStyle = 'blue' ctx.stroke() ctx.fill() } update() { if(this.x + this.radius > canvas.width || this.x-this.radius < 0){ this.dx = -this.dx } if(this.y+this.radius > canvas.height || this.y-this.radius < 0) { this.dy = -this.dy } this.x += this.dx this.y += this.dy this.draw() } } var circle = new Circle(200,200,3,3,30) circle.update() function animate() { requestAnimationFrame(animate) ctx.clearRect(0,0,canvas.width,canvas.height) circle.update() } animate() </script> </body> </html>
|
效果如此文开头的动图,如果注释掉ctx.clearRect(0,0,canvas.width,canvas.height) 你将得到以下结果
加上数组,再加上随机颜色的变化,就可以产生下图的效果了
动画相对静态的图形稍麻烦一点,但若是掌握了requestAnimationFrame以及背后的原理,实现动画就简单多了,当然,也可以使用setTimeout或setInterval,大伙可以试试