一看就懂的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');// 第一个矩形pinkctx.fillStyle = 'pink'ctx.fillRect(10,10,70,30);// 第二个矩形orangectx.fillStyle = 'orange'ctx.fillRect(130,10,70,30);// 第三个矩形yellowctx.fillStyle = 'yellow'ctx.fillRect(250,10,70,30);// 这矩形会自动继承上一次的canvas的状态,颜色是yellowctx.fillRect(370,10,100,100)
</script>

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

<script>const canvas = document.getElementById('canvas');const ctx = canvas.getContext('2d');// 第一个矩形pinkctx.fillStyle = 'pink'ctx.fillRect(10,10,70,30);// 保存第一个canvas的状态ctx.save();// 第二个矩形orangectx.fillStyle = 'orange'ctx.fillRect(130,10,70,30);// 保存第二个canvas的状态ctx.save();// 第三个矩形yellowctx.fillStyle = 'yellow'ctx.fillRect(250,10,70,30);// 保存第三个canvas的状态ctx.save();// 回到第三次保存的canvas状态ctx.restore();// 这矩形会使用第三次的canvas的状态,颜色是yellowctx.fillRect(370,10,100,100)
</script>

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

<script>const canvas = document.getElementById('canvas');const ctx = canvas.getContext('2d');// 第一个矩形pinkctx.fillStyle = 'pink'ctx.fillRect(10,10,70,30);// 保存第一个canvas的状态ctx.save();// 第二个矩形orangectx.fillStyle = 'orange'ctx.fillRect(130,10,70,30);// 保存第二个canvas的状态ctx.save();// 第三个矩形yellowctx.fillStyle = 'yellow'ctx.fillRect(250,10,70,30);// 保存第三个canvas的状态ctx.save();// 回到第三次保存的canvas状态ctx.restore();// 回到第二次保存的canvas状态ctx.restore();// 这矩形会使用第二次的canvas的状态,颜色是orangectx.fillRect(370,10,100,100)
</script>

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

<script>const canvas = document.getElementById('canvas');const ctx = canvas.getContext('2d');// 第一个矩形pinkctx.fillStyle = 'pink'ctx.fillRect(10,10,70,30);// 保存第一个canvas的状态ctx.save();// 第二个矩形orangectx.fillStyle = 'orange'ctx.fillRect(130,10,70,30);// 保存第二个canvas的状态ctx.save();// 第三个矩形yellowctx.fillStyle = 'yellow'ctx.fillRect(250,10,70,30);// 保存第三个canvas的状态ctx.save();// 回到第三次保存的canvas状态ctx.restore();// 回到第二次保存的canvas状态ctx.restore();// 回到第一次保存的canvas状态ctx.restore();// 这矩形会使用第一次的canvas的状态,颜色是pinkctx.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之间相隔20pxctx.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)绘制

canvas理解:一看就懂的save和restore相关推荐

  1. canvas中save和restore的理解和使用

    canvas中save和restore的理解和使用 理解save和restore不一定总是成对出现的 太阳系 理解save和restore不一定总是成对出现的 每个 canvas 的 context ...

  2. 理解Canvas的save()和restore()方法

    save()和restore()方法是绘制复杂图形必不可少的方法.它们分别是用来保存和恢复 canvas 状态的,都没有参数. Canvas 状态是以堆(stack)的方式保存的,每一次调用 save ...

  3. 史密斯圆图串并联口诀_看得懂的史密斯圆图(个人总结)

    看得懂的史密斯圆图(个人总结) 2018-09-11 史密斯圆图(Smith chart)是一款用于电机与电子工程学的圆图,主要用于传输线的阻抗匹配上.一条传输线(transmission line) ...

  4. 《零基础看得懂的C++入门教程 》——(10)面向对象

    一.学习目标 了解C++类是什么 了解类对象与类型修饰一样进行创建 了解了类的属性如何使用 了解了类方法的使用方法 目录 预备第一篇,使用软件介绍在这一篇,C++与C使用的软件是一样的,查看这篇即可: ...

  5. 《零基础看得懂的C++入门教程 》——(5) 容我套个娃 循环

    一.学习目标 了解循环的使用方法 目录 预备第一篇,使用软件介绍在这一篇,C++与C使用的软件是一样的,查看这篇即可:<软件介绍> 想了解编译原理和学习方法点这篇,学习方法和一些原理C++ ...

  6. 《零基础看得懂的C++入门教程 》——(4)条件判断原来如此

    一.学习目标 了解什么是条件判断 了解多个条件判断 了解输入 了解什么是逻辑与.逻辑或 目录 预备第一篇,使用软件介绍在这一篇,C++与C使用的软件是一样的,查看这篇即可:<软件介绍> 想 ...

  7. 《零基础看得懂的C++入门教程 》——(2)什么是数据类型、变量?一看便会

    一.学习目标 了解基本常用的数据类型 了解什么是变量 目录 预备第一篇,使用软件介绍在这一篇,C++与C使用的软件是一样的,查看这篇即可:<软件介绍> 想了解编译原理和学习方法点这篇,学习 ...

  8. 《假如编程是魔法之零基础看得懂的Python入门教程 》——(七)我把魔法变成了积木

    学习目标 了解魔法积木的使用--自定义函数 了解魔法积木的结果反馈--自定义函数返回值 了解魔法积木的原料传递--自定义函数传参 了解魔法积木的类型分类--类与对象 推荐 1.<备受好评的看得懂 ...

  9. 《假如编程是魔法之零基础看得懂的Python入门教程 》——(六)精简魔法更强大

    学习目标 了解对相似逻辑的简化编写--循环 推荐 1.<备受好评的看得懂的C语言入门教程> 目录 第一篇:<假如编程是魔法之零基础看得懂的Python入门教程 >--(一)既然 ...

最新文章

  1. 创建 VXLAN - 每天5分钟玩转 OpenStack(111)
  2. 线程锁与避免线程锁 线程锁检测
  3. “中能融合杯”线下赛感悟
  4. 2、安装和连接mysql
  5. stream of java_Java 8 新特性-Stream更优雅的处理集合入门
  6. 计算机基础知识教程算法,快速掌握!计算机二级公共基础知识教程:算法
  7. 【干货】联邦学习在腾讯微视广告投放中的实践
  8. SM系列国密算法(转)
  9. Mego(05) - Mego Tools使用教程
  10. 为什么程序员老在改 Bug,就不能一次改好吗?
  11. 使用Julia进行图像处理--JuliaImages介绍与基础使用
  12. linux 内核修炼之道——系统调用
  13. python程序设计总结报告_把PPT 总结报告上传
  14. 几种典型信号的频谱 周期单位脉冲序列的频谱
  15. 父亲母亲-山里老房子
  16. 微信支付元转分的正确姿势
  17. 使用腾讯云 SCF 云函数压缩 COS 对象存储文件
  18. Cocos Creator 3.61所有工具软件的使用
  19. 如何评价《就算老公一毛钱股份都没拿到,在我心里,他依然是最牛逼的创业者》里面这位CEO的所作所为?
  20. DeepCTR DeepMatch简单实用指南

热门文章

  1. Netty系列二、Netty原理篇
  2. html语言中复选按钮,命令按钮单选按钮复选按钮
  3. 基于MMdet的cascade MASKRCNN 入门
  4. 2022计算机保研经验贴
  5. hive union all 使用
  6. win10配置密钥对
  7. java、python--差分隐私拉普拉斯分布(Laplace)实现
  8. python:冒泡排序(Bubble Sort)超详细教程!
  9. 《谁说菜鸟不会数据分析》
  10. POJ 1966 枚举 + Dinic