canvas中save和restore的理解和使用

  • 理解save和restore不一定总是成对出现的
  • 太阳系

理解save和restore不一定总是成对出现的

每个 canvascontext 上下文都包含一个保存绘画状态的栈,以下内容都属于绘画状态

  • 当前的变换矩阵
  • 当前的裁剪区域
  • strokeStylefillStylelineWidthlineCapfonttextAlignshadowOffsetX … 这些属性的当前值

当前路径和当前的位图并不属于绘画状态,当前路径是永久存在的,要清除或者重置只能通过 beginPath 方法,而当前位图是属于 canvas 的属性,而不是 context
context.save() 会把当前的状态推入栈中
context.restore() 会从栈中取出最顶部的状态,context 就还原到取出的状态

<canvas id="canvas" width="500" height="300"></canvas><script>
window.addEventListener('load', saveRestore, true)
function saveRestore() {let canvas = document.getElementById('canvas')let context = canvas.getContext('2d')// 绘制了一个红色的矩形context.fillStyle = 'red'context.shadowOffsetX = 5context.shadowOffsetY = 5context.shadowBlur = 4context.shadowColor = 'rgba(0, 255, 0, 0.3)'context.fillRect(20, 20, 50, 150)context.save() // 当前状态1保存(红色,绿色阴影5)推入栈中// 绘制一个绿色的矩形context.fillStyle = 'green'context.shadowOffsetX = 10context.shadowOffsetY = 10context.shadowBlur = 4context.shadowColor = 'rgba(255, 0, 0, 0.3)'context.fillRect(100, 40, 50, 150)context.save() // 当前状态2保存(绿色,红色阴影10)推入栈中// 绘制一个橘色的矩形context.fillStyle = 'orange'context.shadowOffsetX = 15context.shadowOffsetY = 15context.shadowBlur = 4context.shadowColor = 'rgba(0, 0, 255, 0.3)'context.fillRect(190, 60, 50, 150)context.save() // 当前状态3保存(橘色,蓝色阴影15)推入栈中
}
</script>

此时绘制的状态为

现在通过从栈中取出不同的状态绘制圆

...
context.save() // 当前状态3保存(橘色,蓝色阴影15)推入栈中context.restore() // 当前取出的是最顶上的状态(状态3)// 根据以上取出栈中的样式绘制圆
context.beginPath()
context.arc(300, 75, 15, 0, Math.PI * 2, true)
context.fill()

...
context.save() // 当前状态3保存(橘色,蓝色阴影15)推入栈中context.restore() // 当前取出的是最顶上的状态(状态3)
context.restore() // 当前取出的是最顶上的状态(状态2)// 根据以上取出栈中的样式绘制圆
context.beginPath()
context.arc(300, 75, 15, 0, Math.PI * 2, true)
context.fill()

context.save() // 当前状态3保存(橘色,蓝色阴影15)推入栈中context.restore() // 当前取出的是最顶上的状态(状态3)
context.restore() // 当前取出的是最顶上的状态(状态2)
context.restore() // 当前取出的是最顶上的状态(状态1)// 根据以上取出栈中的样式绘制圆
context.beginPath()
context.arc(300, 75, 15, 0, Math.PI * 2, true)
context.fill()

太阳系

下面看一个小案例好好理解和消化一下吧

const WIDTH = 800, SPAN = 40
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = WIDTH
canvas.height = WIDTH
canvas.style.background = '#000'// 轨道
function drawTrack() {for(let i=0; i < 8; i++){ctx.beginPath()ctx.arc(WIDTH / 2, WIDTH / 2, (i + 1) * SPAN, 0, 360, false)ctx.closePath()ctx.strokeStyle = '#fff'ctx.stroke()}
}
drawTrack()// 星球
class Star {constructor(x, y, radius, cycle, startColor, endColor) {// 星球坐标this.x = xthis.y = ythis.radius = radius // 星球半径this.cycle = cycle // 公转周期this.color = null // 新建一个渐变颜色空对象this.time = 0this.startColor = startColorthis.endColor = endColor}draw() {ctx.save()ctx.translate(WIDTH / 2, WIDTH / 2)// rotate 针对的是绘制的图形,以translate的坐标为圆点进行旋转ctx.rotate(this.time * (360 / this.cycle) * Math.PI / 180)// 画星球ctx.beginPath()ctx.arc(this.x, this.y, this.radius, 0, 360, false)ctx.closePath()// 设置星球的渐变填充颜色this.color = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.radius)this.color.addColorStop(0, this.startColor)this.color.addColorStop(1, this.endColor)ctx.fillStyle = this.colorctx.fill()ctx.restore()this.time += 1}
}const sun = new Star(0, 0, 10, 1, '#f00', '#f90')
const mercury = new Star(0, -SPAN, 10, 87.70, '#a69697', '#5c3e40')
const venus = new Star(0, -SPAN * 2, 10, 224.70, '#c4bbac','#1f1315')
const earth = new Star(0, -SPAN * 3, 10, 365.2422, '#78b1e8', '#050c12')
const mars = new Star(0, -SPAN * 4, 10, 686.98, '#cec9b6', '#76422d')
const jupiter = new Star(0, -SPAN * 5, 10, 4332.589, '#cda48e', '#322222')
const satum = new Star(0, -SPAN * 6, 10, 10759.5, '#f7f9e3', '#5c4533')
const uranus = new Star(0, -SPAN * 7, 10, 30799.095, '#f7f9e3', '#19243a')
const neptune = new Star(0, -SPAN * 8, 10, 60152, '#0661b2', '#1e3b73')function move(){ctx.clearRect(0, 0, 1000, 1000)drawTrack()sun.draw()mercury.draw()venus.draw()  earth.draw()mars.draw()jupiter.draw()satum.draw()uranus.draw()neptune.draw()
}setInterval(move, 10)

canvas中save和restore的理解和使用相关推荐

  1. Canvas的save和restore

    在创建新的控件或修改现有的控件时,我们都会涉及到重写控件或View的onDraw方法. onDraw方法会传入一个Canvas对象,它是你用来绘制控件视觉界面的画布. 在onDraw方法里,我们经常会 ...

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

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

  3. Canvas的save和restore方法

    2019独角兽企业重金招聘Python工程师标准>>> Canvas里的两个重要方法,一直很疑惑. save和restore方法是成对出现的,但是restore必然对应一个save方 ...

  4. canvas 的save()和restore()方法

    应用到画布上面的效果是可以累积的,因而就可以利用几个简单的函数来"组合"出效果来.例如,在向屏幕上绘制之前,可能会有一艘飞船需要旋转.变换 和缩放.因为所有效果都对画布起作用,所以 ...

  5. html矩形坐标理解,HTML canvas中translate()与rotate()的理解

    首先,当我们在页面上初始化canvas时,相当于在上面放了一块画布,这块画布我们可以理解为上面有一个坐标系(如下图),左上角是原点,往右是X轴的正方向,往下是Y轴的正方向,我们在画布上绘制的内容都是基 ...

  6. Android画布的保存,Android canvas用法介绍之save()和restore()

    一. 首先讲一下canvas的save 和 restore功能. 这是canvas很有魅力的一个部分. onDraw方法会传入一个Canvas对象,它是你用来绘制控件视觉界面的画布. 在onDraw方 ...

  7. canvas像素操作、save与restore、合成与变形

    一.canvas像素操作 (1)获取图像像素 (2)写入像素数据 (3)创建像素数据 (4)小案例,将canvasA画布的图像复制到canvasB中 二.canvas的save与restore 三.c ...

  8. Android 中Canvas的save(),saveLayer()和restore()解析

    1.save()方法 : 用来保存Canvas的状态,save()方法之后的代码,可以调用Canvas的平移.放缩.旋转.裁剪等操作! 2.restore()方法: 用来恢复Canvas之前保存的状态 ...

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

    一看就懂的save和restore 对于save()和restore()方法,我一开始有一个错误的理解,以为每一步都save()之后restore()就等同于command + z(或者ctrl + ...

最新文章

  1. 判断两个对象是否相等java_判断两个对象的内容是否相等
  2. Java:多线程,CyclicBarrier同步器
  3. html标签教案,第1章 HTML的基本标签-教案
  4. SELinux系列(七)——SELinux安全上下文的修改和设置(chcon和restorecon命令)
  5. 广义逆高斯分布(Generalized Inverse Gaussian Distribution)及修正贝塞尔函数
  6. 玩转 MPlayer(3)
  7. java jshelllink_Jshell使用
  8. C++中的back_inserter
  9. Apollo 6.0 Mid2Mid Planner论文阅读
  10. 微信小程序base64图片转换临时链接
  11. 华为交换机SEP双半环设计方案及配置详细步骤
  12. 基于低代码平台(Low Code Platform)开发中小企业信息化项目
  13. 子网与超网的含义和区别
  14. Windows 7 C 盘隐藏文件分析 删除
  15. XB文件开发详解(上报证监会文件)_入门系列
  16. MOS管及其外围电路设计
  17. java超市管理系统_一个简单的基于控制台的超市管理系统(java)
  18. git status怎么操作_git操作-方向对了,就不怕路远了!-51CTO博客
  19. MATLAB smooth函数平滑处理
  20. 【AppCan开发者故事 第九期】泡泡:KTV包厢里的移动开发技术

热门文章

  1. Running the evict task with compensationTime 0ms
  2. 不再摆烂,浅谈做本地生活如何选择靠谱服务商,少走弯路
  3. HDI激光钻孔和常见问题
  4. 中国自主轿车汽车品牌总汇(已上市)[原创]
  5. 关于python集成dlib
  6. 顺序栈实现十进制转成R进制
  7. 干货 | 携程火车票基于因果推断的业务实践
  8. IBM朱近之:云计算带来全世界IT洗牌
  9. 高考16个突发事件处理方法大全,一定会需要!
  10. Minimum/Maximum Spanning Tree/Forest