(八) JavaScript-Canvas旋转的图片

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

旋转的图片

(八) JavaScript-Canvas旋转的图片

使用 Image类型创建图片对象, 自定义类 Picture

1. 设计网页代码

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
<!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>旋转的图片</title>
<style>
canvas {
position: absolute;
background: black;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight

//创建图片对象


</script>
</body>
</html>

2. 创建一个Image对象

  • 使用 Image 创建一个对象,设置对象的src属性,表示图片的路径,此处将图片和页面放置在同一目录下,所以只需图片名称
1
2
3
//创建图片对象
const cherry = new Image()
cherry.src = 'cherry.png'

3. 在Canvas Context上 画图

  • 图片是异步加载所以需要监听图片加载事件load, 加载完成后才能将图片画到Canvas上
  • 使用translate平移坐标到(100,100), 为了清楚的了解后续图片的旋转
  • 使用rotate 旋转 canvas 0度,也就是不旋转
  • 再增加一个填充矩形,清楚图片位置,无其它作用
  • drawImage 画图,第1个参数为图片对象,第2,3个参数表示图片的坐标,第4,5个参数表示图片宽和高
1
2
3
4
5
6
7
8
cherry.addEventListener('load', function(){
ctx.translate(100,100)
ctx.rotate(0 * Math.PI/360)
ctx.fillStyle= 'black'
ctx.fillRect(0,0,500,500)
ctx.drawImage(cherry, 0, 0, 80, 80)
})

效果如图

4. 再画一个位置不同的图

  • 图片的位置还是平移100,但此时会发现,平移是相对于上面的图片位置
1
2
3
4
5
6
7
8
9
10
11
12
13
cherry.addEventListener('load', function(){
ctx.translate(100,100)
ctx.rotate(0 * Math.PI/360)
ctx.fillStyle= 'black'
ctx.fillRect(0,0,500,500)
ctx.drawImage(cherry, 0, 0, 80, 80)

ctx.translate(100,100)
ctx.rotate(0 * Math.PI/360)
ctx.fillStyle= 'orange'
ctx.fillRect(0,0,500,500)
ctx.drawImage(cherry, 0, 0, 80, 80)
})

效果如图

5. 使用save和restore方法

  • 使用这两个方法后,恢复之前的状态,其实就是将save()之后的绘图操作入栈,调用restore()后出栈,也就是恢复到当前绘图之前的状态,后续画图会使用save()之前的状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cherry.addEventListener('load', function(){
ctx.save()
ctx.translate(100,100)
ctx.rotate(0 * Math.PI/360)
ctx.fillStyle= 'black'
ctx.fillRect(0,0,500,500)
ctx.drawImage(cherry, 0, 0, 80, 80)
ctx.restore()

ctx.translate(100,100)
ctx.rotate(30 * Math.PI/360)
ctx.fillStyle= 'orange'
ctx.fillRect(0,0,500,500)
ctx.drawImage(cherry, 0, 0, 80, 80)
})

效果如图: 桔色背景的图片旋转了30度,平移的位置相对于最开始时的状态; 如果桔色背景下方还要画图,也可以加上save和restore,使得桔色图形的属性设置不会影响后续图形

6. 让图片旋转起来

  • 将绘图代码封装成函数,然后利用window.requestAnimationFrame函数让图片旋转起来
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
const cherry = new Image()
cherry.src = 'cherry.png'

let angle1 = 1 //第一张图片的旋转角度
let angle2 = 10 //第二张图片折旋转角度

function draw() {
//第一张图片
ctx.save()
ctx.translate(canvas.width/2,canvas.height/2)
ctx.rotate(angle1 * Math.PI/360)
ctx.fillStyle= 'black'
ctx.fillRect(0,0,300,300)
ctx.drawImage(cherry, 0, 0, 80, 80)
ctx.restore()

//第二张图片
ctx.save()
ctx.translate(canvas.width/2,canvas.height/2)
ctx.rotate(angle2 * Math.PI/360)
ctx.fillStyle= 'orange'
ctx.fillRect(0,0,300,300)
ctx.drawImage(cherry, 0, 0, 80, 80)
ctx.restore()
}

//图片加载完成后调用draw方法
cherry.addEventListener('load', function(){
draw()

})

//动画函数 animate, 不断地调用画图函数,同时更改两个角度值
function animate() {
ctx.clearRect(0,0,canvas.width, canvas.height)
draw()
angle1+=1
angle2+=10
window.requestAnimationFrame(animate)
}
animate()

效果如图, 也可以去掉矩形填充

7. 旋转的中心点改成图片中心

  • 在画图时改变一下图片的起始绘制坐标
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
let angle1 = 1
let angle2 = 10
function draw() {
ctx.save()
ctx.translate(canvas.width/2,canvas.height/2)
ctx.rotate(angle1 * Math.PI/360)
ctx.fillStyle= 'black'
ctx.fillRect(0,0,300,300)
//更改画图片时的起始坐标
ctx.drawImage(cherry, 0-80/2, 0-80/2, 80, 80)
ctx.restore()

ctx.save()
ctx.translate(canvas.width/2,canvas.height/2)
ctx.rotate(angle2 * Math.PI/360)
ctx.fillStyle= 'orange'
ctx.fillRect(0,0,300,300)
//更改画图片时的起始坐标
ctx.drawImage(cherry, 0-80/2, 0-80/2, 80, 80)
ctx.restore()
}

cherry.addEventListener('load', function(){
draw()
})


function animate() {
ctx.clearRect(0,0,canvas.width, canvas.height)
draw()
angle1+=1
angle2+=10
window.requestAnimationFrame(animate)
}
animate()

效果如图, 尝试去掉填充矩形

再用save() 和 restore() 函数 ,尝试使用面向对象的方法绘图