第一章 基础知识
第七节 绘制表面的保存与恢复
在本书1.2.2小节之中,读者已经看到了如何对绘图环境对象的各个状态进行保存与恢复。绘图环境状态的保存与恢复,可以让开发者很方便地做出临时性的状态改动,这在编码过程中是很常见的。
Canvas绘制环境对象的另外一个关键功能就是可以对绘图表面自身进行保存与恢复。这种绘制表面的保存与恢复功能,可以让开发者在绘图表面上进行一些临时性的绘制动作,诸如绘制橡皮带线条、辅助线(guidewire)或注解(annotation),这些绘制对于许多工作都是很有用的。例如,图1-15中的应用程序可以让用户通过拖动鼠标来交互式地创建多边形,该应用程序会在本书2.13.1小节中讨论。
图1-15 绘制辅助线
检测到鼠标按下的事件之后,应用程序就将绘图表面保存起来。在接下来用户拖动鼠标的过程中,应用程序持续地将按下鼠标那一刻的绘图表面恢复到canvas之中,然后再绘制多边形与相关的辅助线。当用户松开鼠标时,应用程序最后一次将绘图表面恢复到canvas,再将最终不含辅助线的多边形绘制在其上。
程序清单1-7之中,列出了图1-15的应用程序中与绘制辅助线有关的那部分代码。此应用程序的完成程序清单,请查看本书2.11节。
提示:使用getImageData()与putImageData()方法来操作图像
图1.15中的应用程序,使用getImageData()与putImageData()方法来保存与恢复绘图环境的绘图表面。与drawImage()方法一样,getImageData()与putImageData()方法也有几种不同的用途。一种常见的用法是通过它来实现图像滤镜:先获取图像数据,然后处理,最后将它恢复到canvas之上。本书会介绍很多种getImageData()与putImageData()的用法,其中4.5.2.3小节中会讲到如何用这两个方法来实现滤镜效果。
提示:立即模式绘图系统
canvas元素是采用“立即模式”(immediate-mode)来绘制图形的,这意味着它会立刻将你所指定的内容绘制在canvas上。然后,它就会立刻忘记刚才绘制的内容,这表示canvas之中不会包含将要绘制的图形对象列表。某些绘图系统,比如SVG,则会维护一份所绘图形对象的列表。这些绘图系统被叫做“保留模式”(retained-mode )绘图系统。
由于立即模式并不维护所绘制对象的列表,所以相对于保留模式来说,它是一种更加底层的绘图模式。立即模式也更加灵活,因为它是直接向屏幕上绘制的,而不是像保留模式那样,需要调整由绘图系统传递过来的图形对象。
立即模式的绘制系统更适合制作“绘画应用程序”(paint application),这种程序不需要跟踪记录用户所绘制的东西,而保留模式的绘制系统则更适合制作“画图应用程序”(drawing application),此种应用程序可以让用户操作其所创建的图形对象。
在本书2.11节中,你将会看到如何实现一个简单的保留模式绘图系统,该系统将一个画图应用程序所用到的多边形维护在一个数组之中,以便让用户可以通过拖放来改变这些多边形的位置。
程序清单1-7 通过保存与恢复绘图表面来绘制辅助线
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
...
// Save and restore drawing surface...................................
function saveDrawingSurface() {
drawingSurfaceImageData =context.getImageData(0, 0,
canvas.width,
canvas.height);
}
function restoreDrawingSurface() {
context.putImageData(drawingSurfaceImageData, 0,0);
}
// Event handlers.....................................................
canvas.onmousedown = function (e) {
...
saveDrawingSurface();
...
};