Canvas脏矩形应用之截图

3,169 阅读3分钟

前言

本文学习自《HTML5 Canvas核心技术》,了解到了脏矩形技术,本文应用——截图,可以使用到脏矩形技术,以提高应用性能
本文由截图应用的思路与思考,引出脏矩形技术

目录如下

  • 思考与思路
    • 如何进行截图
    • 如何重绘排除矩形干扰
  • 脏矩形技术
  • 总结
  • 参考资料

主要使用的API有getImageData()putImageData(), drawImage()

Demo及CodePen如下(最简单的放大效果):


CodePen打开

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

思考与思路

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


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

如果在鼠标移动过程中没有排除矩形框重绘,就会出现下面这种情况:

综上,我们有两个问题:

  1. 如何进行截图
  2. 如何重绘排除矩形干扰

如何进行截图

如何进行截图比较简单,拖拽矩形时记录位置及长宽(即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核心技术》