最近在写前端代码的过程中,涉及到一些canvas画图的方面,感觉很生疏,以前写android的时候也用过canvas的API画图。然后遇到了一个需求,如果能把状态保存在canvas中,需要的时候再恢复到保存时的状态多方便,于是就查到了canvas的context中提供的save()和restore()。
光看这两个方法的名字,可能会误以为canvas中的save()方法是用来保存当前绘制好的图行,restore()方法则是将后来的改变抹除,恢复到之前保存的图形,然而现实与想象差距甚远。
save()方法把当前绘制状态的配置压入到一个保存配置的栈中。这里的绘画状态配置指坐标原点、变形时的变化矩阵(该矩阵是调用 rotate()、scale() 和 translate() 的结果)、以及图形上下文对象的当前属性值等内容。
restore()方法从栈中弹出存储的图形状态配置并且恢CanvasRenderingContext2D 对象的属性、剪切路径和变换矩阵的值。
例如下面的canvas绘图代码:
1 | var canvas = document.getElementById(id); |
根据代码可知,在rotate()之前先调用save保存了当前状态,也就是说save的状态中是没有旋转90度的。经过一定的绘制后,然后restore状态,即将当前恢复到没有rotate时候的状态了,然后再画一个实心矩形rect。
得到的结果为:
如果我们注释掉restore()方法,即save之后不恢复旋转之前的状态。那么最后绘制的实心矩形是在左下角的,因为存在旋转。如图:
因此,在Canvas中进行绘图的时候,利用这种堆栈技术,来保存和弹出需要的Canvas上下文状态数据。下方是能够存储在堆栈的状态数据属性:
属性 描述
canvas 取得画布Canvas 元素。
fillStyle 填充路径的当前的颜色、模式或渐变。值:字符串、CanvasGradient 对象或 CanvasPattern 对象。
globalAlpha 绘制内容的不透明度。值:在 0.0(完全透明)和 1.0(完全不透明)范围间。默认值为 1.0。
globalCompositeOperation 指定颜色如何与画布上已有颜色组合(合成)
lineCap 指定线条末端如何绘制。值:butt、round和square。默认值是 butt。
lineJoin 指定两条线条如何连接。值:round、bevel和miter。默认值是 "miter"。
lineWidth 绘制线条的线条宽度。默认值是 1.0,且必须大于 0.0。线条在路径上居中,每边有线条宽的一半。
miterLimit 当 lineJoin 为miter时,这个属性指定斜连接长度和线条宽度的最大比率。
shadowBlur 指定羽化阴影的程度。默认值是 0。
shadowColor 把阴影颜色指定为CSS字符串或Web样式字符串,且可包含alpha部分来表示透明度。默认值是 black。
shadowOffsetX, shadowOffsetY 指定阴影水平和垂直偏移。较大值使得阴影化对象漂浮在背景较高位置上。 默认值是 0。
strokeStyle 绘制路径的颜色、模式和渐变。值:字符串、CanvasGradient 对象或 CanvasPattern 对象。
并且可以多次成对的出现save和restore,用来实现多种状态的保存和恢复。