使用html2canvas库对可滚动的dom节点导出全量的图片

页面的dom节点样式

在这里插入图片描述

想要导出的图片样式

在这里插入图片描述

做法

1,使用html2canvas库

先在项目中安装:npm install html2canvas

在vue文件中引用: import html2canvas from "html2canvas";

2, 对于dom节点,不能有overflow: hidden或者 overflow-y:auto的样式设置。

正确写dom的方式是在外层div的类中写样式,内部div用来导出,尽量不要设置样式

<div class="mind-map-scroll-container">
            <div ref="scrollBox">
            ......
            </div>
 </div>
 
.mind-map-scroll-container {
  max-height: 300px; /* 设置最大高度,超出这个高度就会出现滚动条 */
  overflow-y: auto; /* 出现垂直滚动条 */
  position: relative;
  background-color: white;
}

3,主要方法体

// 导出按钮绑定的方法
exportLogs() {
        const node = this.$refs["scrollBox"];
        this.downloadDomPic(
          node,
          `ComputerLog.png`
        );
    },
    downloadDomPic(node, picName) {
      html2canvas(node, { scale: 2, height: node.offsetHeight }).then(
        (canvas) => {
          const a = document.createElement("a");
          a.href = canvas.toDataURL("image/jpg");
          a.download = picName;
          a.click();
        }
      );
    },
<think>嗯,用户在使用html2canvas导出simple-mind-map时遇到了自定义节点样式丢失的问题。首先,我需要了解html2canvas的工作原理。html2canvas是通过解析DOM结构和样式来生成图片的,所以可能某些样式没有被正确捕获。 接下来,用户提到自定义样式丢失,可能的原因有几个。首先,可能是样式作用域的问题,比如在Vue或React中使用scoped样式,导致html2canvas无法正确识别。这时候需要检查样式是否全局应用,或者使用内联样式。 然后,外部字体或图标如果未加载完成,也可能导致导出时缺失。需要确保这些资源在截图前已经加载完毕。此外,异步内容可能导致html2canvas在渲染时内容未完全加载,需要使用延迟截图或者等待异步操作完成。 CSS自定义属性(变量)可能不被html2canvas完全支持,这时候需要转换为固定值。动态绑定的样式,比如通过JavaScript计算的样式,可能需要手动应用到元素上,因为html2canvas无法捕获动态变化。 动画或过渡效果可能会干扰截图,应该在截图前暂停这些效果。跨域资源的问题也可能导致样式丢失,需要确保资源允许跨域访问,并设置useCORS选项为true。 关于解决方案,可以分步骤处理。首先,检查样式作用域,确保使用全局样式或内联样式。其次,预加载外部资源,使用Promise.all等待所有资源加载完成。然后,处理异步内容,使用setTimeout或事件监听确保内容就绪。将CSS变量替换为固定值,手动应用动态样式,暂停动画,设置跨域选项,调整截图时机,以及使用cloneNode克隆节点避免污染原始DOM。 另外,参考了用户提供的引用内容,比如引用[1]中的keyMap.js可能与节点样式映射有关,需要检查是否有样式名称未正确映射。引用[5]提到的资源可能包含其他有用的或工具,帮助解决问题。 用户可能需要具体的代码示例,比如如何设置useCORS,如何克隆节点,或者如何预加载字体。此外,生成相关问题可以帮助用户深入探讨其他可能的问题,如性能优化、跨域处理、动态样式应用等。</think>根据html2canvas的工作原理和样式渲染机制,解决自定义节点样式丢失问题可通过以下步骤实现: ### 一、根本原因分析 1. **CSS作用域问题**:Vue组件作用域样式(scoped CSS)可能导致样式无法被html2canvas正确识别[^1] 2. **外部资源加载**:自定义字体/图标等外部资源未完成加载时触发截图 3. **异步内容渲染**:动态插入的DOM元素未完成渲染时执行截图 4. **CSS变量支持**:部分CSS自定义属性(var)可能不被html2canvas完全支持 5. **样式计算时机**:通过JavaScript动态绑定的样式未触发重绘 ### 二、具体解决方案 ```javascript // 1. 强制样式穿透(Vue环境) const globalStyle = document.createElement('style') globalStyle.innerHTML = ` .custom-node { background: #ffeb3b !important; border: 2px solid #2196f3 !important } ` document.head.appendChild(globalStyle) // 2. 预加载资源 const preloadResources = async () => { await Promise.all([ document.fonts.ready, ...Array.from(document.images).map(img => img.complete ? Promise.resolve() : new Promise(resolve => img.addEventListener('load', resolve) ) ) ]) } // 3. 执行截图 const capture = async () => { await preloadResources() const node = document.querySelector('.mind-map-container') const config = { useCORS: true, // 处理跨域资源[^5] allowTaint: true, logging: true, scale: window.devicePixelRatio * 2, onclone: (clonedDoc) => { // 4. 克隆时注入样式 clonedDoc.head.appendChild(globalStyle.cloneNode(true)) } } // 5. 克隆节点避免污染原始DOM const clone = node.cloneNode(true) clone.style.visibility = 'hidden' document.body.appendChild(clone) html2canvas(clone, config).then(canvas => { // 处理结果... document.body.removeChild(clone) }) } ``` ### 三、关键配置说明 1. **useCORS配置**:必须设置为true才能加载跨域资源[^5] 2. **scale参数**:建议使用设备像素比×2保证高清输出 3. **onclone回调**:克隆文档时补充丢失的样式定义 4. **异步等待机制**:通过Promise.all确保所有资源加载完成 5. **节点克隆策略**:避免原始DOM的交互状态影响截图 ### 四、样式优化建议 1. **强制样式优先级**: ```css /* 使用内联样式覆盖组件样式 */ <div style="color: var(--custom-color);"></div> /* CSS层叠声明 */ .custom-node { /* 添加!important声明 */ font-family: 'CustomFont' !important; /* 转换CSS变量为固定值 */ background: rgb(var(--primary-color)) } ``` 2. **字体加载策略**: ```javascript // 动态加载字体 const font = new FontFace('CustomFont', 'url(/fonts/custom.woff2)') font.load().then(loadedFont => { document.fonts.add(loadedFont) }) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值