Canvas 绘制的图像是可以:放大、缩小、变形、旋转。这些特性和 CSS3 很类似,和 CSS3 不同的是,Canvas 变形的中心点并不是图形的正中心,而是图形的左上角。

状态的保存和释放

save() 的用途是将当前 canvas 的状态保存到堆栈中。restore()的用途是恢复保存在堆栈中的保持状态。

在绘制复杂的图形时,保存绘制状态和恢复绘制状态可以大大减少绘制的计算复杂度。

1
2
3
4
5
6
7
8
9
10
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')

ctx.save() // save the default state

ctx.fillStyle = 'green'
ctx.fillRect(10, 10, 100, 100)

ctx.restore() // restore to the default state
ctx.fillRect(150, 75, 100, 100)

移动 Translating

translate()是用来移动 Canvas 中的中心点位置,在绘制复杂的图案时,tanslatesaverestore可以大大降低绘制图案的计算复杂度。

1
2
3
4
5
6
7
8
9
10
11
12
function draw() {
var ctx = document.getElementById('canvas').getContext('2d')
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
ctx.save()
ctx.fillStyle = 'rgb(' + 51 * i + ', ' + (255 - 51 * i) + ', 255)'
ctx.translate(10 + j * 50, 10 + i * 50)
ctx.fillRect(0, 0, 25, 25)
ctx.restore()
}
}
}

在上一个例子中,每个小正方形的大小相同但位置不同,如果不用translate我们需要在fillRect中设置它的坐标,这样代码上就会变得不易读懂。

旋转 Rotating

rotate(angle)以原点为中心旋转。

旋转的中心点始终是 canvas 的原点,如果要改变它,我们需要用到 translate方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function draw() {
var ctx = document.getElementById('canvas').getContext('2d')
ctx.translate(75, 75)

for (var i = 1; i < 6; i++) {
// Loop through rings (from inside to out)
ctx.save()
ctx.fillStyle = 'rgb(' + 51 * i + ',' + (255 - 51 * i) + ',255)'

for (var j = 0; j < i * 6; j++) {
// draw individual dots
ctx.rotate((Math.PI * 2) / (i * 6))
ctx.beginPath()
ctx.arc(0, i * 12.5, 5, 0, Math.PI * 2, true)
ctx.fill()
}

ctx.restore()
}
}

上面例子中,第一层循环决定环的数量,第二层循环决定每环有多少个点。每环开始之前,我都保存一下 canvas 的状态,这样恢复起来方便。每次画圆点,我都以一定夹角来旋转 canvas,而这个夹角则是由环上的圆点数目的决定的。最里层的环有 6 个圆点,这样,每次旋转的夹角就是 360/6 = 60 度。往外每一环的圆点数目是里面一环的 2 倍,那么每次旋转的夹角随之减半。

缩放 Scaling

scale(x, y)用以改变绘制图形的大小,scale方法接受两个参数。x,y 分别是横轴和纵轴的缩放因子,它们都必须是正值。值比 1.0 小表示缩小,比 1.0 大则表示放大,值为 1.0 时什么效果都没有。

注意: 在用 Canvas 绘制图形中,会发现绘制的图形不够清晰,这时我们可以通过放大 Canvas 图形的大小,并缩小外层包裹 Canvas 标签的大小,达到高清的图形效果。

1
2
3
4
5
.box{zoom:0.5;}

<div class="box">
<canvas id="mycanvas" width="700px" height="700px"></canvas>
</div>

变形 Transforms

transform(a, b, c, d, e, f)变形方法可以实现上面的:平移(translate)/旋转(rotate)/缩放( scale)变换

参数 含义
a 水平缩放绘图
b 水平倾斜绘图
c 垂直倾斜绘图
d 垂直缩放绘图
e 水平移动绘图
f 垂直移动绘图

transform() 方法是对当前坐标系进行矩阵变换。

setTransform(a, b, c, d, e, f) setTransform() 方法重置变形矩阵。先将当前的矩阵重置为单位矩阵(即默认的坐标系),再用相同的参数调用 transform() 方法设置矩阵。

resetTransform()重置当前变形为单位矩阵,它和调用以下语句``是一样的

ctx.setTransform(1, 0, 0, 1, 0, 0);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function draw() {
var ctx = document.getElementById('canvas').getContext('2d')

var sin = Math.sin(Math.PI / 6)
var cos = Math.cos(Math.PI / 6)
ctx.translate(100, 100)
var c = 0
for (var i = 0; i <= 12; i++) {
c = Math.floor((255 / 12) * i)
ctx.fillStyle = 'rgb(' + c + ',' + c + ',' + c + ')'
ctx.fillRect(0, 0, 100, 10)
ctx.transform(cos, sin, -sin, cos, 0, 0)
}

ctx.setTransform(-1, 0, 0, 1, 100, 100)
ctx.fillStyle = 'rgba(255, 128, 255, 0.5)'
ctx.fillRect(0, 50, 100, 100)
}

参考

https://aotu.io/notes/2017/05/25/canvas-img-rotate-and-flip/index.html