最近在写前端代码的过程中,涉及到一些canvas画图的方面,感觉很生疏,以前写android的时候也用过canvas的API画图。然后遇到了一个需求,如果能把状态保存在canvas中,需要的时候再恢复到保存时的状态多方便,于是就查到了canvas的context中提供的save()和restore()。

光看这两个方法的名字,可能会误以为canvas中的save()方法是用来保存当前绘制好的图行,restore()方法则是将后来的改变抹除,恢复到之前保存的图形,然而现实与想象差距甚远。

save()方法把当前绘制状态的配置压入到一个保存配置的栈中。这里的绘画状态配置指坐标原点、变形时的变化矩阵(该矩阵是调用 rotate()、scale() 和 translate() 的结果)、以及图形上下文对象的当前属性值等内容。  
restore()方法从栈中弹出存储的图形状态配置并且恢CanvasRenderingContext2D 对象的属性、剪切路径和变换矩阵的值。  

例如下面的canvas绘图代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var canvas = document.getElementById(id);
var context = canvas.getContext('2d');
context.translate(200, 200);
context.save(); //坐标原点移到画布中心,并保存这个状态
context.rotate(Math.PI/2); //旋转90度
context.beginPath();
context.moveTo(0, -50);
context.lineTo(-50, 0);
context.moveTo(0, -50);
context.lineTo(50, 0);
context.moveTo(0, -50);
context.lineTo(0, 50);
context.closePath(); //画一个向右的箭头
context.restore();
context.fillRect(40, 40, 10, 10); //画一点
context.stroke();

根据代码可知,在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,用来实现多种状态的保存和恢复。