(二) 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
<!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>
canvas {
position: absolute;
background: white;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
canvas {
background: linear-gradient(120deg, #4a3934, #e6d5b9);
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
</script>
</body>

2. 画矩形

  • 掌握几个函数
    • translate() 平移坐标原点到指定坐标位置
    • moveTo(0, 0) 移动到坐标位置(0, 0)
    • beginPath() 开始路径
    • closePath() 关闭路径
    • rotate() 旋转
    • save()
  • 在中心点画一个矩形
    • 使用平移函数 translate() 和 绘制矩形函数rect()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight

//平移
ctx.translate(canvas.width/2, canvas.height/2)
//将坐标设定为(0,0) 也就是平移后的中心
ctx.moveTo(0, 0)
//设置颜色
ctx.strokeStyle = 'black'
//画矩形 坐标和长宽
ctx.rect(0,0,200,200)
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
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight

//平移
ctx.translate(canvas.width/2, canvas.height/2)
//将坐标设定为(0,0) 也就是平移后的中心
ctx.moveTo(0, 0)

//设置颜色
ctx.strokeStyle = 'black'
//画矩形 坐标和长宽
ctx.rect(0,0,200,200)
ctx.stroke()

//一个新的矩形
//旋转一定角度
ctx.rotate(30 * Math.PI/180)
//设定颜色
ctx.strokeStyle = 'red'
//绘制矩形
ctx.rect(0,0,200,200)
ctx.stroke()
</script>

看看效果, 你会发现,两个矩形边框的颜色是最后一次设定的红色, 怎么解决? 其实和画线那篇类似,使用beginPath()

  • 使用beginPath() 重新开始
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
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight

//平移
ctx.translate(canvas.width/2, canvas.height/2)
//将坐标设定为(0,0) 也就是平移后的中心
ctx.moveTo(0, 0)

//设置颜色
ctx.strokeStyle = 'black'
//画矩形 坐标和长宽
ctx.rect(0,0,200,200)
ctx.stroke()

//一个新的矩形
ctx.beginPath() //重新开始新的设置,原来的设置(比如颜色)将不会影响后续图形
//旋转一定角度
ctx.rotate(30 * Math.PI/180)
//设定颜色
ctx.strokeStyle = 'red'
//绘制矩形
ctx.rect(0,0,200,200)
ctx.stroke()
//此行可以写也可以省略
ctx.closePath()
</script>

如下图所示

  • 再画第三个矩形,同时的旋转角度, 边框颜色设定为 blue
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
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight

//平移
ctx.translate(canvas.width/2, canvas.height/2)
//将坐标设定为(0,0) 也就是平移后的中心
ctx.moveTo(0, 0)

//设置颜色
ctx.strokeStyle = 'black'
//画矩形 坐标和长宽
ctx.rect(0,0,200,200)
ctx.stroke()

//一个新的矩形
ctx.beginPath() //重新开始新的设置,原来的设置(比如颜色)将不会影响后续图形
//旋转一定角度
ctx.rotate(30 * Math.PI/180)
//设定颜色
ctx.strokeStyle = 'red'
//绘制矩形
ctx.rect(0,0,200,200)
ctx.stroke()
//此行可以写也可以省略
ctx.closePath()

ctx.beginPath()
ctx.rotate(30 * Math.PI/180)
ctx.strokeStyle = 'blue'
ctx.rect(0,0,200,200)
ctx.stroke()
ctx.closePath()
</script>

可以看到,旋转的角度是相对于上一个矩形,如果不使用save() restore()方法,那么旋转时将相对于上次绘制的形状

  • 在绘制中间的那个矩形时使用save() 和 restore()包裹起来,看看有什么不一样
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
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight

//平移
ctx.translate(canvas.width/2, canvas.height/2)
//将坐标设定为(0,0) 也就是平移后的中心
ctx.moveTo(0, 0)

//设置颜色
ctx.strokeStyle = 'black'
//画矩形 坐标和长宽
ctx.rect(0,0,200,200)
ctx.stroke()

//一个新的矩形
ctx.save()
ctx.beginPath() //重新开始新的设置,原来的设置(比如颜色)将不会影响后续图形
//旋转一定角度
ctx.rotate(30 * Math.PI/180)
//设定颜色
ctx.strokeStyle = 'red'
//绘制矩形
ctx.rect(0,0,200,200)
ctx.stroke()
//此行可以写也可以省略
ctx.closePath()
ctx.restore()

ctx.beginPath()
ctx.rotate(30 * Math.PI/180)
ctx.strokeStyle = 'blue'
ctx.rect(0,0,200,200)
ctx.stroke()
ctx.closePath()
</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
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight

drawRect()

function drawRect() {
//平移
ctx.translate(canvas.width/2, canvas.height/2)
//将坐标设定为(0,0) 也就是平移后的中心
ctx.moveTo(0, 0)
ctx.translate(canvas.width/2, canvas.height/2)
ctx.moveTo(0, 0)
for(let i=0;i<8;i++) {

ctx.strokeStyle = 'hsl(' + Math.random()*360 + ",100%,50%)"
ctx.rect(0,0,200,200)
ctx.rotate(30*Math.PI/180)
ctx.stroke()
}
}
</script>

效果如图,注意没有增加save()和restore()方法

save()和restore()经常在矩阵变换 translate()、缩放 scale()、旋转rotate()中使用, 因为一个Canvas只有一个2d上下文,当执行转换操作时,整个上下文的坐标系都将改变。改变后,如果我们需要将坐标系恢复到原来正常的状态,这时就需要用到save() 和 restore(), 下图中第一次绘制矩形的坐标系和旋转后绘制矩形的坐标系

以上均为绘图基础,为后续绘制复杂的图形和动画打好基础