一 、状态的保存和恢复 Saving and restoring state
Canvas状态存储在栈中,每当save()方法被调用后,当前的状态就被推送到栈中保存。可以调用任意多次 save方法。每一次调用 restore 方法,上一个保存的状态就从栈中弹出,所有设定都恢复。
其中绘画状态包括如下:
- 当前应用的变形(即移动,旋转和缩放)
- 以及下面这些属性:strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, lineDashOffset, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font, textAlign, textBaseline, direction, imageSmoothingEnabled
- 当前的裁切路径(clipping path)
方法 | 描述 |
---|---|
save() | 保存画布(canvas)的所有状态 |
restore() | save 和 restore 方法是用来保存和恢复 canvas 状态的,都没有参数。Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。 |
save和restore的结合使用
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
ctx.fillRect(10, 10, 480, 480);
ctx.save(); // 保存一
ctx.fillStyle = '#87ceeb';
ctx.fillRect(50, 50, 400, 400);
ctx.save(); // 保存二
ctx.fillStyle = '#3498dbaa';
ctx.fillRect(100, 100, 300, 300);
ctx.restore(); // 恢复保存二
ctx.fillRect(150, 150, 200, 200);
ctx.restore(); // 恢复保存一
ctx.fillRect(220, 220, 60, 60);
}
二、移动 Translating
用来移动 canvas 和它的原点到一个不同的位置。translate 方法同时让我们可以任意放置这些图案,而不需要在 fillRect() 方法中手工调整坐标值。
在做变形之前先保存状态是一个良好的习惯。大多数情况下,调用 restore 方法比手动恢复原先的状态要简单得多。
方法 | 描述 |
---|---|
translate(x, y) | translate 方法接受两个参数。x 是左右偏移量,y 是上下偏移量。 |
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
ctx.save(); // 在translate移动之前进行保存,目的是可以回到初始的状态,重新绘制下一个。
ctx.fillStyle = `#${j}${i}5`;
ctx.fillText(`${j}${i}`, j * 100 + 100, i * 100 + 100);
ctx.translate(j * 100 + 10, i * 100 + 10);
ctx.fillRect(10, 10, 80, 80);
ctx.restore();
}
}
}
三、旋转 Rotating
它用于以原点为中心旋转 canvas。
方法 | 描述 |
---|---|
rotate(angle) | 这个方法只接受一个参数:旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。 |
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
ctx.translate(250, 250);
for (var i = 1; i < 6; i++) {
ctx.save();
ctx.fillStyle = 'rgb(' + 51 * i + ',' + (255 - 51 * i) + ',255)';
for (var j = 0; j < i * 6; j++) {
ctx.rotate((Math.PI * 2) / (i * 6));
ctx.beginPath();
ctx.arc(0, i * 30, 10, 0, Math.PI * 2, true);
ctx.fill();
}
ctx.restore();
}
}
四、缩放 Scaling
用它来增减图形在 canvas 中的像素数目,对形状,位图进行缩小或者放大。
画布初始情况下, 是以左上角坐标为原点的第一象限。如果参数为负实数, 相当于以x 或 y轴作为对称轴镜像反转(例如, 使用translate(0,canvas.height); scale(1,-1); 以y轴作为对称轴镜像反转, 就可得到著名的笛卡尔坐标系,左下角为原点)。
方法 | 描述 |
---|---|
scale(x, y) | scale 方法可以缩放画布的水平和垂直的单位。两个参数都是实数,可以为负数,x 为水平缩放因子,y 为垂直缩放因子,如果比1小,会缩小图形, 如果比1大会放大图形。默认值为1, 为实际大小。 |
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
ctx.font = '80px Times New Roman';
ctx.save();
ctx.scale(-1, 1);
ctx.fillText('Canvas', -300, 100);
ctx.restore();
}
五、变形 Transforms
这个方法允许对变形矩阵直接修改。
方法 | 描述 |
---|---|
transform(a, b, c, d, e, f) | 这个方法是将当前的变形矩阵乘上一个基于自身参数的矩阵 |
setTransform(a, b, c, d, e, f) | 这个方法会将当前的变形矩阵重置为单位矩阵,然后用相同的参数调用 transform 方法。如果任意一个参数是无限大,那么变形矩阵也必须被标记为无限大,否则会抛出异常。从根本上来说,该方法是取消了当前变形,然后设置为指定的变形,一步完成。 |
resetTransform() | 重置当前变形为单位矩阵,它和调用以下语句是一样的:ctx.setTransform(1, 0, 0, 1, 0, 0); |
参数说明:
- a (m11):水平方向的缩放
- b(m12):竖直方向的倾斜偏移
- c(m21):水平方向的倾斜偏移
- d(m22):竖直方向的缩放
- e(dx):水平方向的移动
- f(dy):竖直方向的移动
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);
}