当前位置: 首页 > 文档资料 > HTML5 Canvas 实战 >

2.6 使用上下文栈来保存和恢复样式

优质
小牛编辑
132浏览
2023-12-01

在创建较为复杂的HTML画布应用时,你将发现你需要一种恢复之前样式的方法,以便在绘制过程中,不必设置或重置不同点的诸多样式属性。幸运的是,HTML5的画布API为我们提供了访问画布上下文状态栈的途径,状态栈允许我们保存和恢复上下文状态。本节,我们将通过保存上下文状态、设置全局透明度、绘制一个透明的圆、恢复状态栈到之前设置的全局透明度,并绘制一个不透明的矩形,来演示状态栈的工作原理。请看下图!

保存和恢复样式
图2-6 保存和恢复样式

准备工作

在探讨画布状态栈之前,有必要了解一下栈这个数据结构的工作原理(如果你已经了解,可以直接跳到工作原理部分)。栈是一个后进先出(LIFO)的数据结构。栈有三个主要操作,分别是压栈(push)、弹栈(pop)、取栈顶元素(top)。当一个元素被压栈,它被添加到栈顶。当一个元素被弹栈,栈顶元素被从栈中移除。取栈顶元素操作只是简单地返回栈顶元素而已。

栈的工作原理
图2-7 栈的工作原理

请看上图,它表示一个栈在所有动作下的状态。第1步,我们从包含一个元素"a"的栈出发。第2步,"b"元素被压栈。第3步,"c"元素被压栈。第4步,执行弹栈操作,该操作会移除最后压栈的元素。由于元素"c"位于栈顶,所以它是被移除的元素。第5步,我们再一次弹栈,该操作会移除最后压栈的元素。由于元素"b"位于栈顶,所以它是被移除的元素。

下一节我们将看到,当状态随着时间变化,而要保存栈的状态,再通过弹栈来恢复状态时,栈是一个很好的数据结构。

绘制步骤

按照以下步骤,在透明的圆之上,绘制一个不透明的矩形:

1. 定义2D画布上下文:

window.onload  = function(){
  var canvas  = document.getElementById("myCanvas");
  var context = canvas.getContext("2d");

2. 绘制矩形:

  //绘制矩形
  context.beginPath();
  context.rect(150,  30,  130,  130);
  context.fillStyle  = "blue";
  context.fill();

3. 调用save()方法保存上下文状态,使用globalAlpha属性设置画布的全局透明度,绘制圆,然后调用restore()方法恢复画布状态:

  // 使用save-restore 组合包裹绘制圆的代码
  context.save();
  context.globalAlpha = 0.5;  //设置全局透明度
  context.beginPath();
  context.arc(canvas.width / 2, canvas.height / 2, 70, 0, 2 * Math.PI, false);
  context.fillStyle  = "red"; context.fill();
  context.restore();

4. 绘制另一个矩形(它将是非透明的),以表明画布上下文状态已经被恢复到设置全局透明度之前的状态:

  //绘制另一个矩形
  context.beginPath();
  context.rect(canvas.width - (150  +  130), canvas.height - (30  + 130), 130, 130);
  context.fillStyle  = "green"; context.fill();
};

5. 在HTML文档的body部分嵌入canvas标签:

<canvas id="myCanvas" width="600" height="250" style="border:1px solid black;">
</canvas>

工作原理

从前面的代码可以看到,通过save-restore组合包裹绘制圆的代码,实质上我们把save()方法和restore()方法之间的样式包裹起来,这样一来,它们不影响后面绘制的图形。save-restore 组合可被认为是引入样式作用域的一种方式,跟JavaScript在函数中包含变量作用域的方式类似。尽管你可能会说:“噢,它听上去好像是把globalAlpha设置为1的一个更复杂的方法”。等一下,伙计。在现实世界中,一般情况下,你将会为不同部分的代码处理大量的不同样式的组合。在这种情况下,save-restore组合就是一个救星。如果没有save-restore组合,要编写复杂的HTML画布应用,就像是用一大块只使用全局变量的JavaScript代码,来构建一个复杂的Web应用。哎呀!

了解更多

在第4章 掌握变形中我们将会看到,状态栈的另一种常见用法是保存和恢复变形状态。

相关参考

  • 第4章 使用栈处理多个变形