13

前端页面中可以使用JS将整个网页或一部分区域截取成图片并导出。

今天刚做了一次这个功能,和大家分享一下经验。

使用html2canvas将dom转换成canvas

网页截图的第一步,就是将dom转换图片。目前比较好用的处理方式是先将dom转换成canvas,再从canvas中导出图片。

可以使用html2canvas这个库来实现dom转换成canvas。

https://github.com/niklasvh/h...

示例代码:

html2canvas(document.querySelector("#capture")).then(canvas => {
    document.body.appendChild(canvas)
});

将canvas导出成图片

canvas展示的时候,本身就有保存为图片的功能。

如果需要的话,也可以在JS中手动操控。

canvas 有两个API可以用来导出图片,分别是 toDataURL 和 toBlob

https://developer.mozilla.org...

https://developer.mozilla.org...

toDataURL可以把canvas导出成图片的data url,toBlob 则是转换成Blob对象,Blob对象可以保存成文件。

如果要在新窗口中展示图片等,使用toDataURL导出的 data url就可以了,而要直接导出成文件的话,使用toBlob更好一些。

调用 canvas.toBlob(),现在我们有了一个Blob对象,下一步是保存Blob到文件中。

保存Blob为文件

Canvas.toBlob 的文档 https://developer.mozilla.org... 中有提到如何保存Blob到文件,不过使用起来略为复杂。我推荐使用 filesaver 来解决这个问题。参见 https://github.com/eligrey/Fi...

Filesaver 支持保存 canvas 到文件,代码如下:

import { saveAs } from 'file-saver/FileSaver';
canvas.toBlob(function(blob) {
    saveAs(blob, "pretty image.png");
});

调用 saveAs 之后,浏览器就会执行下载的动作。根据浏览器的设置,可能会直接下载,或弹出保存对话框。

至此,对网页中的一部分进行截图并保存成文件就完成了。

图片调优

导出的图片基本上会保持原有的样式,只有一小部分不支持。参见 https://html2canvas.hertzen.c...

但是如果截取的范围比较大,那么导出的图片有可能会出现模糊的情况。有可能是文字模糊,也有可能是图片模糊等。这个时候就需要对图片进行调优

图片调优指的是在 html 导出至 canvas的这个阶段调优,调优方法是修改 html2canvas的参数。

html2canvas(element, options);

调优主要有两个方向:

  1. 对于高分屏,比如Retina,有可能会需要调高 scale 参数。它的默认值是 window.devicePixelRatio,一般是1,我修改成了1.2,感觉效果会好一点
  2. 如果截图范围比较大,可能会出现文字模糊的情况。这个时候可以用 windowWidth 和 windowHeight 指定渲染时用的窗口宽度和高度。将宽度调小可以降低模糊程度。

还有一些其它选项,参见 https://html2canvas.hertzen.c...

最后,附上参考代码:

import { saveAs } from 'file-saver/FileSaver'
import html2canvas from 'html2canvas'
 
 
handleDownloadCapture = async () => {
  const reportDom = document.querySelector('.report-container')
  const actualWidth = reportDom.offsetWidth || 1000
  const actualHeight = reportDom.offsetHeight || 2000
  const factor = 0.6
  const canvas = await html2canvas(reportDom, {scale: 1.2, windowWidth: actualWidth * factor, windowHeight: actualHeight * factor})
  const filename = this.getExportFilename()
  canvas.toBlob(blob => saveAs(blob, filename))
}


鱼肚
92 声望3 粉丝

Node.js开发工程师