canvas理解:一看就懂的save和restore

一看就懂的save和restore

对于save()和restore()方法,我一开始有一个错误的理解,以为每一步都save()之后restore()就等同于command + z(或者ctrl + z),其实save()保存的只是CanvasRenderingContext2D对象的状态以及对象的所有属性,并不包括这个对象上绘制的图形。
如果对CanvasRenderingContext2D还不是很清楚又想要详细理解CanvasRenderingContext2D上的属性和方法的可以看这里

总结

  • save:用来保存最近一次的Canvas的状态和属性。
  • restore:用来获取save保存的Canvas之前的状态和属性。防止save后对Canvas执行的平移、放缩、旋转、错切、裁剪等可以改变画布的操作对后续的绘制的影响。

下面我会从颜色属性接平移属性对save和restore做解析,至于其他的放缩、旋转、错切、裁剪我就不一一说明,原理都是一样的,感兴趣的自行实验

  1. 颜色属性
<script>
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  // 第一个矩形pink
  ctx.fillStyle = 'pink'
  ctx.fillRect(10,10,70,30);

  // 第二个矩形orange
  ctx.fillStyle = 'orange'
  ctx.fillRect(130,10,70,30);

  // 第三个矩形yellow
  ctx.fillStyle = 'yellow'
  ctx.fillRect(250,10,70,30);

	// 这矩形会自动继承上一次的canvas的状态,颜色是yellow
	ctx.fillRect(370,10,100,100)
</script>

渲染效果:如果不保存之前的canvas状态,这最新一次的图形会自动继承上一次的canvas状态(上面的图形4就继承了图形3的颜色,表现为填充颜色为yellow)
在这里插入图片描述

<script>
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  // 第一个矩形pink
  ctx.fillStyle = 'pink'
  ctx.fillRect(10,10,70,30);
  // 保存第一个canvas的状态
  ctx.save();
  
  // 第二个矩形orange
  ctx.fillStyle = 'orange'
  ctx.fillRect(130,10,70,30);
  // 保存第二个canvas的状态
  ctx.save();

  // 第三个矩形yellow
  ctx.fillStyle = 'yellow'
  ctx.fillRect(250,10,70,30);
  // 保存第三个canvas的状态
  ctx.save();

  // 回到第三次保存的canvas状态
  ctx.restore();

	// 这矩形会使用第三次的canvas的状态,颜色是yellow
  ctx.fillRect(370,10,100,100)
</script>

渲染效果:由于依次保存了三次canvas的状态,然后restore了一次,所以canvas状态回到了倒数第一次save的状态(图形4就继承了图形3的颜色,表现为填充颜色为yellow)
在这里插入图片描述

<script>
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  // 第一个矩形pink
  ctx.fillStyle = 'pink'
  ctx.fillRect(10,10,70,30);
  // 保存第一个canvas的状态
  ctx.save();
  
  // 第二个矩形orange
  ctx.fillStyle = 'orange'
  ctx.fillRect(130,10,70,30);
  // 保存第二个canvas的状态
  ctx.save();

  // 第三个矩形yellow
  ctx.fillStyle = 'yellow'
  ctx.fillRect(250,10,70,30);
  // 保存第三个canvas的状态
  ctx.save();

  // 回到第三次保存的canvas状态
  ctx.restore();
  // 回到第二次保存的canvas状态
  ctx.restore();

	// 这矩形会使用第二次的canvas的状态,颜色是orange
  ctx.fillRect(370,10,100,100)
</script>

渲染效果:由于依次保存了三次canvas的状态,然后restore了两次次,所以canvas状态回到了倒数第二次save的状态(图形4就继承了图形2的颜色,表现为填充颜色为orange)

在这里插入图片描述

<script>
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  // 第一个矩形pink
  ctx.fillStyle = 'pink'
  ctx.fillRect(10,10,70,30);
  // 保存第一个canvas的状态
  ctx.save();
  
  // 第二个矩形orange
  ctx.fillStyle = 'orange'
  ctx.fillRect(130,10,70,30);
  // 保存第二个canvas的状态
  ctx.save();

  // 第三个矩形yellow
  ctx.fillStyle = 'yellow'
  ctx.fillRect(250,10,70,30);
  // 保存第三个canvas的状态
  ctx.save();

  // 回到第三次保存的canvas状态
  ctx.restore();
  // 回到第二次保存的canvas状态
  ctx.restore();
  // 回到第一次保存的canvas状态
  ctx.restore();

	// 这矩形会使用第一次的canvas的状态,颜色是pink
  ctx.fillRect(370,10,100,100)
</script>

渲染效果:由于依次保存了三次canvas的状态,然后restore了三次,所以canvas状态回到了倒数第三次save的状态,也即是第一次save(图形4就继承了图形1的颜色,表现为填充颜色为pink)
在这里插入图片描述

**总结:**经过上面的实例,我们可以把save看成是一个入栈的过程,save一次,就向栈里面push一次cnavas的状态,而restore就是一个出栈的过程,每restore一次,就相当于弹出一次之前save的canvas状态,当前的canvas状态也就恢复成出栈的那个canvas状态,后面的图形的绘制就会在这个canvas状态之上绘制

在这里插入图片描述

  1. 平移(translate)
<script>
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
	// 矩形pink和矩形orange之间相隔20px
  ctx.fillStyle='pink';
  ctx.fillRect(10,10,100,100);

  ctx.fillStyle='orange';
  ctx.fillRect(130,10,100,100);
</script>

渲染效果:没有平移之前,pink和orange的矩形都是相对于红色坐标的(0,0)绘制
在这里插入图片描述

<script>
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');

  // X坐标
  ctx.beginPath();
  ctx.lineWidth = 10;
  ctx.strokeStyle = 'red'
  ctx.moveTo(0,0);
  ctx.lineTo(600,0);
  ctx.stroke();
  // Y坐标
  ctx.beginPath();
  ctx.lineWidth = 10;
  ctx.strokeStyle = 'red'
  ctx.moveTo(0,0);
  ctx.lineTo(0,600);
  ctx.stroke();

  ctx.fillStyle='pink';
  ctx.fillRect(10,10,100,100);

  // 画布水平和垂直都平移了110px,相当于画布的之前的(0,0)坐标,变成了(110,110)
  ctx.translate(110,110);
  // X坐标
  ctx.beginPath();
  ctx.lineWidth = 5;
  ctx.strokeStyle = 'green'
  ctx.moveTo(0,0);
  ctx.lineTo(600,0);
  ctx.stroke();
  // Y坐标
  ctx.beginPath();
  ctx.lineWidth = 5;
  ctx.strokeStyle = 'green'
  ctx.moveTo(0,0);
  ctx.lineTo(0,600);
  ctx.stroke();

  ctx.fillStyle='orange';
  ctx.fillRect(130,10,100,100);
</script>

渲染效果:添加了ctx.translate(110,110)之后,相当于画布的之前的(0,0)坐标,变成了(110,110),orange矩形就相对于绿坐标(110,110)绘制

在这里插入图片描述

<script>
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  // X坐标
  ctx.beginPath();
  ctx.lineWidth = 10;
  ctx.strokeStyle = 'red'
  ctx.moveTo(0,0);
  ctx.lineTo(600,0);
  ctx.stroke();
  // Y坐标
  ctx.beginPath();
  ctx.lineWidth = 10;
  ctx.strokeStyle = 'red'
  ctx.moveTo(0,0);
  ctx.lineTo(0,600);
  ctx.stroke();

  ctx.fillStyle='pink';
  ctx.fillRect(10,10,100,100);
  // 保存此时的canvas状态
  ctx.save();
  // 画布水平和垂直都平移了110px,相当于画布的之前的(0,0)坐标,变成了(110,110),坐标从红色变成绿色
  ctx.translate(110,110);
  // X坐标
  ctx.beginPath();
  ctx.lineWidth = 5;
  ctx.strokeStyle = 'green'
  ctx.moveTo(0,0);
  ctx.lineTo(600,0);
  ctx.stroke();
  // Y坐标
  ctx.beginPath();
  ctx.lineWidth = 5;
  ctx.strokeStyle = 'green'
  ctx.moveTo(0,0);
  ctx.lineTo(0,600);
  ctx.stroke();
  
  ctx.fillStyle='orange';
  ctx.fillRect(130,10,100,100);
  // 恢复之前保存的canvas状态,此时颜色yellow的矩形相对于之前的红色坐标绘制
  ctx.restore();
  ctx.fillStyle='yellow';
  ctx.fillRect(130,10,100,100);
</script>

渲染效果:使用ctx.save()来保存之前的canvas状态,使后面的yellow矩形绘制不受ctx.translate(110,110);影响,用ctx.restore()还原canvas状态,使矩形yellow是相当于红坐标(0,0)绘制

在这里插入图片描述

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值