前言
本文学习自《HTML5 Canvas核心技术》,了解到了脏矩形技术,本文应用——截图,可以使用到脏矩形技术,以提高应用性能
本文由截图应用的思路与思考,引出脏矩形技术
目录如下
- 思考与思路
- 如何进行截图
- 如何重绘排除矩形干扰
- 脏矩形技术
- 总结
- 参考资料
主要使用的API有getImageData(),putImageData(), drawImage()
Demo及CodePen如下(最简单的放大效果):

CodePen打开
代码放到CodePen之中,同时由于图片放在图床,存在跨域问题,不知道是什么原因,有时代码会因跨域报错,导致出现bug,所以推荐把代码copy下来

思考与思路
其实截图功能非常简单,如下流程图:

但是,仅仅只是按照此流程图的话,用户体验会很不好,比如
没有绘制矩形框标识选中区域所以,我们一个截图应用至少应该拥有矩形框标识选中区域,而
矩形框也是绘制在canvas画布上,会影响对原图的截取,所以具体至Canvas绘图中流程图应该如下:
如果在鼠标移动过程中没有排除矩形框重绘,就会出现下面这种情况:

综上,我们有两个问题:
- 如何进行截图
- 如何重绘排除矩形干扰
如何进行截图
如何进行截图比较简单,拖拽矩形时记录位置及长宽(即rubberBandRectangle),在mouseup时通过drawImage()及rubberBandRectangle记录进行截图
如何重绘排除矩形干扰
这里我们引出脏矩形的概念
所谓脏矩形技术,就是哪里脏了,就(仅仅)把脏了的那块区域重绘。而不是每次直接性的重绘。
——摘自《2D渲染引擎中的脏矩形技术》
这里写出两种思路,第一种是mousemove时不断调用getImageData(),通过putImageData()修复及去除矩形痕迹,第二种是mousedown时记录Canvas原图,mousemove时通过对原图截取,进行局部重绘
ps:《HTML5 Canvas核心技术》书中仅把第二种思路归为
脏矩形技术,但在查阅相关定义之后,脏矩形更多可理解为局部重绘,所以我认为两种思路都是对脏矩形的应用。欢迎大佬们交流
由于getImageData()较慢,第二种思路的效率高于第一种;这里我还是贴出两种思路的伪代码
第一种:不断调用getImageData()
在mousemove阶段,我们不断执行如下(伪)代码
//去除局部的矩形痕迹
if (imageData !== null) {
context.putImageData(imageData,
rubberBandRectangle.left,
rubberBandRectangle.top);
}
......
//记录局部图像
imageData = context.getImageData(rubberBandRectangle.left,
rubberBandRectangle.top,
rubberBandRectangle.width,
rubberBandRectangle.height);
......
第二种:通过原图截取进行局部重绘
mousedown阶段,记录原图(部分代码):
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
接着在mousemove阶段,选取imageData局部,进行canvas上的局部重绘
ctx.putImageData(imageData, 0, 0,
rubberBandRectangle.left,
rubberBandRectangle.top,
rubberBandRectangle.width ,
rubberBandRectangle.height);
结语
这是一个最基本的截图应用,操作难度并不难,主要在于重绘去除矩形痕迹
不足之处,欢迎大佬交流
参考资料
2D渲染引擎中的脏矩形技术
What's the definition of dirty rectangle?
Dirty Rectangles?What is that?
《HTML5 Canvas核心技术》