save()和restore()
save()和restore()方法是绘制复杂图形必不可少的方法.它们分别是用来保存和恢复 canvas 状态的,都没有参数。
- canvas.save()用来保存先前状态的
- canvas.restore()用来恢复之前保存的状态
注:两种方法必须搭配使用,否则没有效果
对canvas中特定元素的旋转平移等操作实际上是对整个画布进行了操作, 默认情况下那么每一次绘图都会在上一次的基础上进行操作,最后导致错位。
比如 页面上的元素相对于原点30度递增旋转,30,60,90.如果不使用save 以及 restore
就会变成30, 90, 150,每一次在前一次基础上进行了旋转。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
canvas{
background-color:#CECECE;
}
</style>
</head>
<body>
<canvas width="400" height="400">
</canvas>
<script type="text/javascript">
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
ctx.translate(100,10)
for(var i = 1;i<3;i++){
ctx.rotate(i*30* Math.PI/180 );
ctx.fillRect(100,10,100,50)
}
</script>
</body>
</html>
按照正常的运算第二个图形应该旋转的是60度但是实际上他旋转了90度.这就是上面所述的会累加直线的旋转的度数.
利用canvas.save()和canvas.restore()就可以完美的解决问题;
在改变画布旋转之前前保存画布,在旋转之后回复之前保存的画布
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
ctx.translate(100,10)
for(var i = 1;i<3;i++){
//保存当前画布的环境
ctx.save();
ctx.rotate(i*30* Math.PI/180 );
ctx.fillRect(100,10,100,50)
//回复之前保存的画布
ctx.restore();
}
canvas 在绘画的过程中难免会改变整个画布,导致坐标错位等情况,所以在我们改变整个画布之前使用save() 保存一下画布,在我们需要他回复之前的状态的时候使用restore()回到之前的状态
注意:回到之前保存的状态是不把画布的内容回到之前的状态,而是把画布的配置 比如原点,旋转角度,画笔的颜色等该变成之前的状态
比如一下情况
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
ctx.translate(100,10)
for(var i = 1;i<3;i++){
//保存当前画布的环境
ctx.save();
if(i==1){
ctx.fillStyle="red"
}
ctx.fillRect(100,10+i*100,100,50)
//回复之前保存的画布
ctx.restore();
}
当 i ==1 的时候画笔填充色为红色
这是我们理想中的结果,但是当去掉canvas.save()和canvas.restore()时就达我们想象要的效果
方向推断可以得 可以把画笔的颜色变回到之前保存的状态,那么画笔的其他被配置是否也可以.
在Canvas环境中绘图时,canvas 状态是以堆(stack)的方式保存的,每一次调用 save 方法,当前的状态就会被推入堆中保存起来
如上所述用堆栈的原理来解释,就是调用save()方法时,将记录当前的绘图状态,并压入一个堆栈中;接着调用restore()方法时,就会把上一次记录的绘图状态从堆栈中弹出。
需要注意的是,出栈的次数不能多于入栈的次数,故程序中restore()方法调用的次数不应该比save()方法多。