canvas-状态的变换及图形变换
2019-06-11 本文已影响0人
我只会吃饭
一、状态的保存
有两种方法可以跟踪上下文的状态变化
- save()
调用这个方法,将当前所有的设置放入一个栈结构,保存起来
然后可以对上下文进行其他修改;
需要注意的是:save() 方法保存的只是对绘图上下文的设置和变换,不会保存绘图上下文的内容
- restore()
等想要回到之前保存的设置时,可以调用restore()方法,在保存设置的栈结构中向前返回一级,恢复之前的状态
连续调用save()可以把更多设置保存到栈结构中,之后再连续调用restore()则可以以一级一级返回
栗子:
ctx.beginPath();
ctx.translate(50, 50); // 第一次移动
ctx.fillStyle = 'skyblue';
ctx.rect(100, 100, 200, 200);
ctx.fill();
// 开始画第二个正方形
ctx.beginPath();
ctx.fillStyle = 'orange';
ctx.translate(100, 100); // 第二次移动
ctx.rect(100, 100, 100, 100);
ctx.fill();
image.png
当第二次移动位置的时候,承接的第一次移动的距离,因此何时如何保存当前上下文的状态及变换变得尤为重要
下面,我们使用save及restore方法:
// 先保存当前设置及变换
ctx.save();
// 开始画第一个正方形
ctx.beginPath();
ctx.translate(50, 50); // 第一次移动
ctx.fillStyle = 'skyblue';
ctx.rect(100, 100, 200, 200);
ctx.fill();
// 画完第一个回到起初状态
ctx.restore();
// 开始画第二个正方形
ctx.beginPath();
ctx.fillStyle = 'orange';
ctx.translate(100, 100); // 第二次移动
ctx.rect(100, 100, 100, 100);
ctx.fill();
// 画完第二个再回到起初状态
ctx.restore();
image.png
二、图形变换
- 位移 translate(x, y)
上面的栗子使用的就是位移
- 旋转 rotate(deg)
旋转当前的绘图
ctx.beginPath();
ctx.fillStyle = 'skyblue';
ctx.rect(0, 0, 100, 100);
ctx.rect(250, 250, 100, 100);
ctx.fill();
// 旋转15deg
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.rotate(Math.PI / 180 * 15);
ctx.rect(0, 0, 100, 100);
ctx.rect(250, 250, 100, 100);
ctx.fill();
// 再次旋转15deg
ctx.beginPath();
ctx.fillStyle = 'blue';
ctx.rotate(Math.PI / 180 * 15);
ctx.rect(0, 0, 100, 100);
ctx.rect(250, 250, 100, 100);
ctx.fill();
image.png
- 缩放 scale(xs, ys);
对绘图进行缩放,所有之后的绘图也会被缩放。定位也会被缩放
ctx.beginPath();
ctx.fillStyle = 'skyblue';
ctx.rect(50, 50, 100, 100);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.scale(1.5, 1.5);
ctx.rect(50, 50, 100, 100);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = 'blue';
ctx.scale(1.5, 1.5);
ctx.rect(50, 50, 100, 100);
ctx.fill();
image.png
- 矩阵 transform(a, b, c, d, e, f);
transform(水平缩放, 水平倾斜, 垂直倾斜, 垂直缩放, 水平位移, 垂直位移)
以上的变换效果会产生级联,导致在一级一级的不断累积
- setTransform(): 可以让之前的transform的累积效果失效
setTransform(水平缩放, 水平倾斜, 垂直倾斜, 垂直缩放, 水平位移, 垂直位移)
ctx.beginPath();
ctx.fillStyle = 'skyblue';
ctx.rect(0, 0, 100, 100);
ctx.fill();
// 移动50
ctx.beginPath();
ctx.fillStyle = 'green';
// ctx.rotate(Math.PI / 180 * 15);
ctx.setTransform(1, 0, 0, 1, 50, 50);
ctx.rect(0, 0, 100, 100);
ctx.fill();
// 移动150
ctx.beginPath();
ctx.fillStyle = 'blue';
ctx.setTransform(1, 0, 0, 1, 150, 150);
ctx.rect(0, 0, 100, 100);
ctx.fill();
image.png