前端html2canvas和dom-to-image实现截图功能

本文介绍了前端实现截图的需求及痛点,详细比较了html2canvas和dom-to-image-more两个库的优缺点。在遇到html2canvas的截图延迟、样式错乱等问题后,作者转向使用dom-to-image-more,虽然存在一些问题,但总体表现更优。文章还分享了截图知识点,包括Canvas和SVG截图原理,并提供了使用教程和解决跨域问题的方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

需求

历劫过程

截图知识点

html2canvas

文档地址

封装

使用教程 

dom-to-image-more

文档地址

封装

使用教程

解决跨域问题

以下是我花了大把时间,薅秃头得出来的最终结果, dom-to-image-more截图时间快到可以让复杂的页面仅需2-3S就能完成截图,内容有点多,请保持耐心慢慢看。

需求

用户想要反馈平台当前页面的各种问题,所以系统的反馈功能需要提供一个一键截图并上传图片的功能。

历劫过程

一开始系统使用的是html2canvas,但是会出现以下一些问题:

  • 截图时间过长
  • 图片会出现样式错乱
  • 不能支持截取micoapp嵌入的页面
  • 图片内数据缺失

后来,准备替换掉这个组件,开始调研,发现dom-to-image组件看着还不错的样子,但是据说也存在一些问题,而它的升级版dom-to-image-more优化了不少功能,所以开始采用dom-to-image-more,不过调研过程中,也发现它存在一下问题:

  • 图片中svg-icon(雪碧图组件)空白
  • 系统中图片采用阿里云服务器存储,需要修改js文件(代码看下面)
  • background背景样式需要稍微做修改
  • 截图时间按页面复杂程度决定,如果存在图片多的话,会慢很多,因为它会去请求各种图片的接口

总而言之,个人感觉dom-to-image-more更好一些,截屏更加全面且错误率更少点。

截图知识点

前端的两种截图方式:1、Canvas截图,通过遍历DOM克隆一份副本,将此副本在Canvas上重新绘制,并根据DOM的样式应用在对应的绘制元素上,再通过Canvas生成图片。转换过程可理解成:DOM→Canvas→Image,例如html2canvas。

2、SVG截图,通过遍历DOM克隆一份副本,利用SVG的foreignObject把DOM作为外部资源嵌套在SVG中,将此SVG在Canvas上重新绘制,并根据DOM的样式应用在对应的绘制元素上,再通过Canvas生成图片。转换过程可理解成:DOM→SVG的ForeignObject→Canvas→Image,例如dom-to-image-more。

总结:两种前端截图方式最后都是通过把DOM绘制到Canvas,再通过Canvas输出图片。

html2canvas
文档地址

Options | html2canvas

封装
import html2Canvas from 'html2canvas'
import { getToken } from '@/utils/auth'

export default {
  install(Vue, options) {
    Vue.prototype.GetCanvasToImg = function() {
      let pa
### 使用 `dom-to-image` 替代 `html2canvas` 实现复杂 DOM 截图 #### 一、背景分析 在前端开发中,当需要实现网页截图功能时,通常会考虑使用 `html2canvas` 或者 `dom-to-image` 这类工具。然而,正如提到的那样,`html2canvas` 存在一个显著缺陷——它难以灵活调整生成图片的样式[^1]。相比之下,`dom-to-image` 提供了一种更强大的解决方案,尤其适合处理复杂的 DOM 结构。 `dom-to-image` 的核心优势在于它可以将 HTML 元素转换为 SVG 图像后再渲染至 Canvas 上,从而保留原始样式的完整性并支持更多高级特性[^2]。 --- #### 二、`dom-to-image` 的工作原理 `dom-to-image` 主要分为以下几个阶段完成截图操作: 1. **克隆目标 DOM 节点**:复制待截图区域的内容。 2. **构建 SVG 表示形式**:将克隆后的 DOM 转化为基于 SVG 的表示方法。 3. **绘制到 Canvas**:利用 Canvas API 将 SVG 数据重绘出来。 4. **导出图像文件**:最终从 Canvas 中提取 Base64 编码或者 Blob 对象用于保存或显示。 这种流程使得即使面对高度定制化的 CSS 属性(如阴影效果、渐变填充等),也能较好地还原视觉表现[^3]。 --- #### 三、常见问题及其解决方案 ##### 1. 处理跨域资源加载失败的情况 如果页面中的某些子元素涉及到了外部链接(比如字体图标 Font Awesome 或远程图片),可能会触发 CORS 错误而导致部分数据丢失。对此可以通过配置参数来规避: ```javascript import domtoimage from 'dom-to-image'; function captureElement(node) { return domtoimage.toPng(node, { style: {}, // 自定义额外样式 filter: null, // 排除特定节点不参与捕获 width: node.offsetWidth, height: node.offsetHeight, quality: 0.95, // 设置压缩质量 bgcolor: '#ffffff', // 定义背景颜色,默认透明 allowTaint: false, // 是否允许污染 canvas (true 可能导致无法下载) useCORS: true // 启用跨源请求头访问外链素材 }); } ``` 注意这里启用了 `useCORS=true` 参数以确保所有网络请求都携带必要的权限声明;同时建议开发者确认服务器端已开放对应资源路径上的 Access-Control-Allow-Origin 响应头部信息。 ##### 2. 支持动态内容更新同步反映于结果之中 对于那些依赖 JavaScript 动态注入的数据项而言,在调用截屏函数之前应当给予充分时间让这些变化生效完毕再继续下一步骤。例如下面例子展示了如何等待异步任务完成后才执行实际抓取动作: ```javascript async function delayedCapture(targetNode){ await new Promise(resolve => setTimeout(resolve, 800)); // 等待半秒延迟 const capturedDataURI = await captureElement(targetNode); console.log(`Captured image URL:\n${capturedDataURI}`); } // Example usage: delayedCapture(document.querySelector('#complexDom')); ``` 此处引入了一个简单的延时机制以便适应实际情况下的性能差异。 ##### 3. 高分辨率输出适配 Retina 显示器 为了使生成出来的图形更加清晰锐利特别是在高 DPI 设备环境下,则需手动计算放大比例因子应用于整个过程中每一个尺寸测量环节之上: ```javascript const scaleRatio = window.devicePixelRatio || 1; captureElementWithScaleFactor(myTargetDiv, scaleRatio).then((highResImageData)=>{ alert('High resolution version ready!'); }); /** * @param {HTMLElement} element - The target container whose content will be rendered into an image. * @param {number} scaleFactor - Multiplier applied against original dimensions when rendering final output. */ function captureElementWithScaleFactor(element,scaleFactor=1){ let rectBounds = element.getBoundingClientRect(); return domtoimage.toBlob( element,{ ...otherOptionsHere,...{ width :rectBounds.width*scaleFactor , height:rectBounds.height*scaleFactor } }, mimeType='image/jpeg', jpegQuality=.75 ); } ``` 上述代码片段示范了怎样通过乘积运算扩大宽度与高度数值进而获得更高精度的结果[^3]。 --- #### 四、总结推荐实践要点 综上所述,采用 `dom-to-image` 来代替传统意义上的 `html2canvas` 是完全可行而且具备诸多技术层面的优势所在。不过与此同时也要留意几个关键事项以免陷入不必要的麻烦当中去: - 确认项目环境满足 ES Modules 导入语法兼容条件; - 测试期间密切观察是否存在未授权访问受限资产的现象发生; - 根据具体业务场景合理设定各项选项值达到最佳平衡状态。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉红茶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值