(一) 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()
  • 画一根线
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 <script>

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
//平移到坐标canvas中心点,那么原点就是此坐标点
ctx.translate(canvas.width/2, canvas.height/2)

//从中心点到 (200, 0) 这个位置画一根线
ctx.moveTo(0, 0)
ctx.lineTo(200, 0)
//设定线的颜色样式 为 黑色
ctx.strokeStyle = "black"
//设定线宽
ctx.lineWidth = 5
ctx.stroke()
</script>

如下图所示,注意此时并没有使用beginPath()也没有使用closePath()

  • 在第一根线的基础上, 再画一根线
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 <script>

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
//平移到坐标canvas中心点,那么原点就是此坐标点
ctx.translate(canvas.width/2, canvas.height/2)

//从中心点到 (200, 0) 这个位置画一根线
ctx.moveTo(0, 0)
ctx.lineTo(200, 0)
//设定线的颜色样式 为 黑色
ctx.strokeStyle = "black"
//设定线宽
ctx.lineWidth = 5
ctx.stroke()

ctx.strokeStyle = "red"
ctx.lineTo(200, 30)
ctx.lineWidth = 5
ctx.stroke()
</script>

结果如图所示: 第一根线的样式完全变成了第二根线的样式,原因是画完第一根线时并没有关闭路径,也就是没有调用closePath()方法,导致第二根线的起始点会在第一根的结束坐标开始

  • 在画完第一根线后closePath(), 关闭路径后,下一根线的起点将从原点(0,0)开始, 但是第一根线的颜色从black变成了red
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>

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
//平移到坐标canvas中心点,那么原点就是此坐标点
ctx.translate(canvas.width/2, canvas.height/2)

//从中心点到 (200, 0) 这个位置画一根线
ctx.moveTo(0, 0)
ctx.lineTo(200, 0)
//设定线的颜色样式 为 黑色
ctx.strokeStyle = "black"
//设定线宽
ctx.lineWidth = 10
ctx.stroke()
ctx.closePath() //关闭路径

ctx.strokeStyle = "red"
ctx.lineTo(200, 20)
ctx.lineWidth = 5
ctx.stroke()
</script>

  • 为了让每一根线的样子能独立出来,相互不影响,需要使用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
<script>

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
//平移到坐标canvas中心点,那么原点就是此坐标点
ctx.translate(canvas.width/2, canvas.height/2)

//第一根线路径开始
ctx.beginPath()
//从中心点到 (200, 0) 这个位置画一根线
ctx.moveTo(0, 0)
ctx.lineTo(200, 0)
//设定线的颜色样式 为 黑色
ctx.strokeStyle = "black"
//设定线宽
ctx.lineWidth = 10
ctx.stroke()
ctx.closePath() //关闭路径

//第二根线路径开始
ctx.beginPath()
ctx.strokeStyle = "red"
ctx.moveTo(0,0) //或者直接使用lineTo(0,0)
ctx.lineTo(200, 20)
ctx.lineWidth = 5
ctx.stroke()
</script>

  • 下面利用旋转函数rotate画出下面的图形, 需要知晓以下数学知识
    • 1弧度是 大约 57.2958角度
    • 弧度转换为角度:乘以 180,除以 π
    • 角度转换为弧度:乘以 π,除以 180
    • 弧度是基于圆的半径的纯计量单位
    • 在一个半圆上有 π 弧度,也等于 180°, 所以: π 弧度 = 180° 那么 : 1弧度 = 180°/π = 57.2958……°

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
<script>

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
//平移到坐标canvas中心点,那么原点就是此坐标点
ctx.translate(canvas.width/2, canvas.height/2)

//第一根线路径开始
ctx.beginPath()
//从中心点到 (200, 0) 这个位置画一根线
ctx.moveTo(0, 0)
ctx.lineTo(200, 0)
//设定线的颜色样式 为 黑色
ctx.strokeStyle = "black"
//设定线宽
ctx.lineWidth = 10
ctx.stroke()
ctx.closePath() //关闭路径

//第二根线路径开始
ctx.beginPath()
//旋转30度 30*Math.PI/180 是一个转换公式
ctx.rotate(30*Math.PI/180)
ctx.strokeStyle = "red"
ctx.moveTo(0,0)
ctx.lineTo(200, 0)
ctx.lineWidth = 5
ctx.stroke()

//第三根线路径开始
ctx.beginPath()
ctx.rotate(30*Math.PI/180)
ctx.strokeStyle = "yellow"
ctx.moveTo(0,0)
ctx.lineTo(200, 0)
ctx.lineWidth = 5
ctx.stroke()

//第四根线路径开始
ctx.beginPath()
ctx.rotate(30*Math.PI/180)
ctx.strokeStyle = "pink"
ctx.moveTo(0,0)
ctx.lineTo(200, 0)
ctx.lineWidth = 5
ctx.stroke()
</script>
  • 如果再加上**ctx.save()ctx.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
40
41
42
43
44
45
46
47
48
49
50
51
52
<script>

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
//平移到坐标canvas中心点,那么原点就是此坐标点
ctx.translate(canvas.width/2, canvas.height/2)

//第一根线路径开始
ctx.beginPath()
//从中心点到 (200, 0) 这个位置画一根线
ctx.moveTo(0, 0)
ctx.lineTo(200, 0)
//设定线的颜色样式 为 黑色
ctx.strokeStyle = "black"
//设定线宽
ctx.lineWidth = 10
ctx.stroke()
ctx.closePath() //关闭路径

//第二根线路径开始
ctx.beginPath()
//旋转30度 30*Math.PI/180 是一个转换公式
ctx.rotate(30*Math.PI/180)
ctx.strokeStyle = "red"
ctx.moveTo(0,0)
ctx.lineTo(200, 0)
ctx.lineWidth = 5
ctx.stroke()

//第三根线路径开始
ctx.save()
ctx.beginPath()
ctx.rotate(30*Math.PI/180)
ctx.strokeStyle = "yellow"
ctx.moveTo(0,0)
ctx.lineTo(200, 0)
ctx.lineWidth = 5
ctx.stroke()
ctx.restore()


//第四根线路径开始
ctx.beginPath()
ctx.rotate(30*Math.PI/180)
ctx.strokeStyle = "pink"
ctx.moveTo(0,0)
ctx.lineTo(200, 0)
ctx.lineWidth = 5
ctx.stroke()
</script>

结果是第四根线不再依据第三根线旋转角度,而是依据第二根红线旋转角度,对于第四根线来说就好像第三根线不存在一样, 据此可以明白save() restore()的作用

  • 利用函数+循环实现,颜色使用HSL随机
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>

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
//平移到坐标canvas中心点,那么原点就是此坐标点
ctx.translate(canvas.width/2, canvas.height/2)

drawLine();

function drawLine() {
ctx.translate(canvas.width/2, canvas.height/2)
for(let i=0;i<12;i++) {
ctx.beginPath()
ctx.strokeStyle = 'hsl('+Math.random()*360+",100%,50%)"
ctx.lineWidth = 5
ctx.rotate(30*Math.PI/180)
ctx.lineTo(0, 0)
ctx.lineTo(200, 0)
ctx.stroke()
ctx.closePath()
}
}
</script>

效果如下图:

利用上面所了解的知识点,能画出一个五角星吗? 下一篇来试试