JavaScript实现网页截图导出方案

发布时间:2025-05-02 12:32:34 浏览次数:4


网页截图导出不是一个非常高频的需求,但时不时的也会遇到。这里总结一下系统的解决方案,然后从中选择合适自己的。

截图导出可以看到是两个功能,第一步实现截图,第二步实现导出也就是下载能力。



截图实现


首先,我们必须明白正常javascript是运行在浏览器里的,本身没有截图的能力。所以要想实现截图,必须通过其他迂回方案实现,废话少说,直接上结论。

https://html2canvas.hertzen.com/


实现原理:
html2canvas 是一个 HTML 渲染器,屏幕截图是基于 DOM,因此生成的图片并不一定 100% 一致,因为它没有制作实际的屏幕截图,而是根据页面上可用的信息构建屏幕截图。
文档介绍的比较清楚,canvas只是去还原dom的展示效果。

根据实现原理,可以想象,实现成本还是比较高的,需要解析dom和css样式,而且css样式不一定能完美映射到canvas,另外还会受限于canvas收到的一些限制,比如跨域资源问题。


实现原理:

核心要素是SVG 的一个特性,允许在 <foreignObject> 标签中包含任意的 HTML 内容。所以为了渲染该dom节点,需要如下步骤:

递归克隆原始DOM节点

计算节点和每个子节点的样式并将其复制到相应的克隆,并且要重新创建伪元素,因为它们当然不会以任何方式克隆

嵌入网页字体,链接所有css样式到style标签,应用到clone节点

嵌入图像
在 <img> 元素中嵌入图像 URL
背景 CSS 属性中使用的内嵌图像,以类似于字体的方式

将克隆的节点序列化为 XML

将 XML 包裹到 <foreignObject> 标签中,然后包裹到 SVG 中,然后使其成为数据 URL

创建一个以 SVG 作为源的 Image 元素,并将其呈现在您也已创建的离屏画布上,然后从画布中读取内容

嗯,这就是svg方式实现了,和canvas方式一样,需要我们处理dom,css和资源,但是后续的绘制渲染工作交给了浏览器,所以减轻了很多工作量和代码量。

服务端方案

Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。这里具体就不介绍了,我们只使用它的截图功能。

这个就是真正的截图能力了,官网有demo。

考虑到业务层的页面都需要用户访问权限,所以正确的步骤应该是:

启动一个node服务,利用puppeter实现截图能力

客户端发起一个请求,携带cookie

第一步启动的服务处理此请求,生成图片,地址返回给客户端

客户端拿到图片资源,进行下载即可


对比

html2canvas

优点

简单页面截图效果还可以,兼容性还好

缺点

部分样式无法支持

复杂页面,惨不忍睹。

cors可以解决跨域,但是实际应用还是问题百出

实现非常复杂,难以改动

在我们项目几乎无法使用

dom-to-image

优点

实现简单,可下载后自行改动源码

还原度良好,尤其chrome支持非常好

缺点

safari支持不是很好,不过一些问题可以解决(canvas节点会导出空白,如果使用绘图引擎的话,建议转化成svg引擎绘图)

ie,edge 无法使用

基本能支持业务需求

后端截图

优点

真实截图,终极方案,无兼容问题

缺点

实现流程稍微繁琐

需要考虑 用户权限认证问题


导出实现


导出也就是下载文件到本地

a标签

原理是通过a标签的download属性实现下载。

// 基本使用
<a href="/images/xxxxx.jpg" download="filename">
// 脚本触发
const download = (filename, url) => {
    let a = document.createElement('a'); 
    a.style = 'display: none'; // 创建一个隐藏的a标签
    a.download = filename;
    a.href = url;
    document.body.appendChild(a);
    a.click(); // 触发a标签的click事件
    document.body.removeChild(a);
}

blob文件流对象

这个需要服务端支持,发起请求,服务端返回数据流,然后前端触发下载。
具体就不多说了,网上有很多文章。

这里推荐几个封装好的下载文件库


评论 0

上一篇: 没有符合条件的博文
温馨提示 ×
商品已成功加入购物车!
购物车共 0 件商品
去购物车结算
微信 ×

打开微信,点击底部的“发现”

使用“扫一扫”即可将网页分享至朋友圈

链接 ×
复制