网页截图功能调研
背景
在某一开发项目中有这样一个需求,用户框选出一段内容给后端做OCR识别。
咋一看挺简单的,就是个鼠标框选功能,但是如何拿到框选区域的内容呢???换个角度来看这不就是QQ截图么,拿到截取的图片传给后端问题就解决了。
别急别急啊,很可惜的是JS并没有提供相关的方法,浏览器也没有提供对应的API。😩 😫
网页截图的两种方式
前端要实现页面截图的功能,现在比较常见的方式是使用开源的截图npm库,一般使用比较多的npm库有 html2canvas 和 dom-to-image
以上两种常见的npm库,对应着两种常见的实现原理。实现前端截图,一般是使用图形API重新绘制页面生成图片,基本就是SVG(dom-to-image)和Canvas(html2canvas)两种实现方案,两种方案目标相同,即把DOM转为图片。
dom-to-image
dom-to-image库主要使用的是SVG实现方式,简单来说就是先把DOM转换为SVG然后再把SVG转换为图片。
具体用法这里不做细究,只做基本介绍
1 | const node = document.getElementById('node'); |
html2canvas
html2canvas库主要使用的是Canvas实现方式,主要过程是手动将dom重新绘制成canvas,因此,它只能正确渲染可以理解的属性,有许多CSS属性无法正确渲染。
1 | html2canvas(dom, option).then(canvas=>{ |
通过对比两者的基本用法发现,它们都需要传入一个具体的dom对象才能使用,但是用户截图所选内容不一定是一个完整的dom,而且就算是一个完整dom我们也没法获取到对应的dom。否则就会不需要大费周章的使用三方件了。完了此路不通啊
不要急少年,直接使用不行那就迂回吧。首先通过上面两种方法将整个网页转换成图片,然后我们在图片里截取所需内容就OK啦。
这就用到了canvas的
https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/drawImage
基本用法如下:
1 | // 传入截取原图,起始点距左上角的位置和截取的宽高 |
很可惜SVG并没有相同的能力,所以dom-to-image不适用我们的任意截图功能。
框选功能
这个很简单,就是监听鼠标的mousedown、mousemove、mouseup事件获取鼠标点击位置和移动距离。在mouseup里传入所得到的的位置信息给canvas。
1 | // 获取包含图片的base64,也可以使用使用别的方法直接下载图片,核心就是拿到图片信息 |
到此一个简单的网页任意截图功能就完成了。下面回归到我们的需求本身
业务分析
首页项目中需要截图的内容本身就是一个图片,那么其实就不需要使用三方件搞得那么复杂。就是一个框选功能加新建canvas再调用drawImage方法已经满足需求了。
总结
虽然最终需求实现不是太复杂,但是在调研过程中我们也理清了如何实现一个完整的截图功能,重新熟悉了canvas相关的知识也算是颇有收获。后期遇到一个真正的截图功能也我们可以从容胜任。好了就这样吧。