canvas理解:一看就懂的save和restore
一看就懂的save和restoresave:用来保存最近一次的Canvas的状态。restore:用来获取save保存的Canvas之前的状态。防止save后对Canvas执行的平移、放缩、旋转、错切、裁剪等可以改变画布的操作对后续的绘制的影响。下面我会从颜色属性接平移属性对save和restore做解析,至于其他的放缩、旋转、错切、裁剪我就不一一说明,原理都是一样的,感兴趣的自行实验颜色属性&l
一看就懂的save和restore
对于save()和restore()方法,我一开始有一个错误的理解,以为每一步都save()之后restore()就等同于command + z(或者ctrl + z),其实save()保存的只是CanvasRenderingContext2D对象的状态以及对象的所有属性,并不包括这个对象上绘制的图形。
如果对CanvasRenderingContext2D还不是很清楚又想要详细理解CanvasRenderingContext2D上的属性和方法的可以看这里
总结
- save:用来保存最近一次的Canvas的状态和属性。
- restore:用来获取save保存的Canvas之前的状态和属性。防止save后对Canvas执行的平移、放缩、旋转、错切、裁剪等可以改变画布的操作对后续的绘制的影响。
下面我会从颜色属性接平移属性对save和restore做解析,至于其他的放缩、旋转、错切、裁剪我就不一一说明,原理都是一样的,感兴趣的自行实验
- 颜色属性
<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状态之上绘制
- 平移(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)绘制
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)