(三) JavaScript Canvas 画多边形-多角星

JavaScript 是前端核心, 掌握这门语言是步入前端高手行列必经之路,噢,别忘了还有TypeScript, 学习它还需要OOP知识, 底层的浏览器原理、HTTP协议也必不可少, 此系列文章记录使用JavaScript和Canvas进行游戏开发, 有游戏才有趣!!!

(二) JavaScript Canvas 画多边形-多角星

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!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;
box-sizing: border-box;
}

body {
overflow: hidden;
background-color: black;
}

#canvas1 {
background-color: white;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>

/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas1.getContext('2d')
console.log(canvas1)
console.log(ctx);

//定义画布Canvas的宽和高
canvas.width = window.innerWidth
canvas.height = window.innerHeight
</script>
</body>
</html>

2. 绘制六角星形

  • 多边形由线组成,先把第一根线画好,此处选择从中心点向上绘制
  • 初始坐标为(0,0) 此时设置为画布Canvas的中心点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
//定义画布Canvas的宽和高
canvas.width = window.innerWidth
canvas.height = window.innerHeight

ctx.beginPath()
//平移到canvas中心点
ctx.translate(canvas.width/2, canvas.height/2)
//设置颜色为红色
ctx.strokeStyle='red'
//设置线宽
ctx.lineWidth = 3
//移动到坐标(0,0)
ctx.moveTo(0, 0)
//结束坐标
ctx.lineTo(0, -100)
//画线
ctx.stroke()


</script>

效果如下图所示

  • 下面再画第二根线,要注意的是不要closePath(),让第二根线从第一根线的结束点开始画,也就是从(0, -100)开始
  • 绘制时需要旋转, 旋转会将整个坐标系旋转具体角度或弧度
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
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
//定义画布Canvas的宽和高
canvas.width = window.innerWidth
canvas.height = window.innerHeight

ctx.beginPath()
//平移到canvas中心点
ctx.translate(canvas.width/2, canvas.height/2)
//设置颜色为红色
ctx.strokeStyle='red'
//设置线宽
ctx.lineWidth = 3
//移动到坐标(0,0)
ctx.moveTo(0, 0)
//结束坐标
ctx.lineTo(0, -100)

//绘制第二根线
ctx.rotate(Math.PI/6)
ctx.lineTo(0, -50)

//画线
ctx.stroke()

</script>

如下图所示,第二根线的开始点为(0, -100) 结束点为 (0, -50), 整个坐标系rotate (旋转) 了 Math.PI/6 个角度

rotate 前和rotate 后的坐标系如图所示,蓝色表示是rotate 前, 红色表示rotate后

  • 接下来再用同样的方法,先rotate,然后再设定结束坐标
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
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
//定义画布Canvas的宽和高
canvas.width = window.innerWidth
canvas.height = window.innerHeight

ctx.beginPath()
//平移到canvas中心点
ctx.translate(canvas.width/2, canvas.height/2)
//设置颜色为红色
ctx.strokeStyle='red'
//设置线宽
ctx.lineWidth = 3
//移动到坐标(0,0)
ctx.moveTo(0, 0)
//结束坐标
ctx.lineTo(0, -100)

//绘制第二根线
ctx.rotate(Math.PI/6)
ctx.lineTo(0, -50)
//绘制第三根线
ctx.rotate(Math.PI/6)
ctx.lineTo(0, -100)

//画线
ctx.stroke()

</script>

效果如下图所示

  • 接下来就只需要重复以上第二根线和第三根线的绘制步骤
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
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
//定义画布Canvas的宽和高
canvas.width = window.innerWidth
canvas.height = window.innerHeight

ctx.beginPath()
//平移到canvas中心点
ctx.translate(canvas.width/2, canvas.height/2)
//设置颜色为红色
ctx.strokeStyle='red'
//设置线宽
ctx.lineWidth = 3
//移动到坐标(0,0)
ctx.moveTo(0, 0)
//结束坐标
ctx.lineTo(0, -100)

//绘制第二根线
ctx.rotate(Math.PI/6)
ctx.lineTo(0, -50)
//绘制第三根线
ctx.rotate(Math.PI/6)
ctx.lineTo(0, -100)

//重复以上两根线的绘制
ctx.rotate(Math.PI/6)
ctx.lineTo(0, -50)
ctx.rotate(Math.PI/6)
ctx.lineTo(0, -100)

ctx.rotate(Math.PI/6)
ctx.lineTo(0, -50)
ctx.rotate(Math.PI/6)
ctx.lineTo(0, -100)

ctx.rotate(Math.PI/6)
ctx.lineTo(0, -50)
ctx.rotate(Math.PI/6)
ctx.lineTo(0, -100)

ctx.rotate(Math.PI/6)
ctx.lineTo(0, -50)
ctx.rotate(Math.PI/6)
ctx.lineTo(0, -100)

ctx.rotate(Math.PI/6)
ctx.lineTo(0, -50)
ctx.rotate(Math.PI/6)
ctx.lineTo(0, -100)

//画线
ctx.stroke()

</script>

结果如下图所示, 六边形就画成了,但是多了一根线,可以直接将这行代码ctx.moveTo(0, 0) 注释掉即可

3. 使用循环实现

  • 上面代码可以使用循环实现
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
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
//定义画布Canvas的宽和高
canvas.width = window.innerWidth
canvas.height = window.innerHeight

ctx.beginPath()
//平移到canvas中心点
ctx.translate(canvas.width/2, canvas.height/2)
//设置颜色为红色
ctx.strokeStyle='red'
//设置线宽
ctx.lineWidth = 3

ctx.lineTo(0, -100)

for(let i=0;i<6;i++) {
ctx.rotate(Math.PI/6)
ctx.lineTo(0, -50)
ctx.rotate(Math.PI/6)
ctx.lineTo(0, -100)
}
ctx.stroke()
//画线
ctx.stroke()

</script>

效果和上面一样,还可以改成7角星或更多角,只需要改一个数字即可

将6更改为10

1
2
3
4
5
6
for(let i=0;i<10;i++) {
ctx.rotate(Math.PI/10)
ctx.lineTo(0, -50)
ctx.rotate(Math.PI/10)
ctx.lineTo(0, -100)
}

4. 定义函数绘制多边形或多角星

  • 定义成函数后,更改几个参数就可以绘制出不同的形状
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
<!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;
box-sizing: border-box;
}

body {
overflow: hidden;
background-color: black;
}

#canvas {
background-color: white;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')

//定义画布Canvas的宽和高
canvas.width = window.innerWidth
canvas.height = window.innerHeight
//x,y也可以为任意值,此处是将其平移动中心位置
let x = canvas.width/2
let y = canvas.height/2
//绘制一个八角形,第四个参数如果是等于1时将会是一个多边形
drawShape(x, y, 50, 1.5, 8)

function drawShape(x, y, radius, inset, n) {
ctx.fillStyle = 'hsl(3,100%,50%)'
ctx.beginPath()
ctx.save()
ctx.translate(x,y) //平移到x,y的位置
ctx.moveTo(0, 0-radius) //开始点 如果radius为100此时的坐标就为 (0,-100)
for(let i=0;i<n;i++) {
ctx.rotate(Math.PI/n)//旋转
ctx.lineTo(0, 0-radius*inset) //中心点和内角点的距离
ctx.rotate(Math.PI/n)
ctx.lineTo(0, 0-radius) //中心点和外角点的距离
}
ctx.restore()
ctx.closePath()
ctx.stroke()
ctx.fill()//填充
}
</script>
</body>
</html>
  • 调用时可传递不同的参数值,看看效果吧
  • drawShape(x, y, 50, 1.5, 8)

  • drawShape(x, y, 50, 1.5, 8)

  • drawShape(x, y, 100, 2.8, 5)

以上均为绘图基础,为后续绘制复杂的图形和动画打好基础. 最后一个函数稍微复杂一点点。用到的技术也就是前面篇章里介绍的。