一、html2Canvas的使用
首先还是需要讲一下html2Canvas的简单使用,本案例为vue3中使用html2Canvas:
1.1 安装
npm install html2canvas
1.2 引入
import html2canvas from 'html2canvas'
1.3 导出
async function exportImage() {
if (miniMapEl.value) {
const canvasObj = await html2canvas(miniMapEl.value, {
backgroundColor: null,
scale: 1.5
});
const img = canvasObj.toDataURL('image/png');
// 可以选择将图片作为下载链接
const linkEl = document.createElement('a');
linkEl.href = img;
linkEl.setAttribute('download', 'export_mindmap.png');
linkEl.click();
}
}
二、问题集锦
2.1 带有滚动条的元素标签无法截全
可以看到上面截图是我的html,它是带有滚动条的,当使用html2Canvas截图,结果如下:
截图结果将会跟html中一致,滚动部分会被截断,非常地所见即所得。
解决方案:
解决方案并不是通过设置去解决的,而是另辟蹊径,在截图按钮按下时放弃滚动,将其宽高设置为内容的宽高来截图:
<div :style="{ height: isScreenshot ? 'auto' : '800px', width: isScreenshot ? `${width}px` : '100%'">
</div>
当点击截图按钮时将isScreenshot变为true:
async function onClickScreenshot() {
isScreenshot.value = true
await nextTick()
// html2Canvas截图操作
...
// 截完图记得把样式变回去
isScreenshot.value = false
}
vue3中 await nextTick() 可以保证渲染样式完成后进行操作。
2.2 div背景色出现奇怪灰色
原始html渲染如下:
截图结果如下:
可以看到每个div外圈出现了莫名灰色区域,无法消除。
解决方案:
2.2.1 scale增大
const canvasObj = await html2canvas(miniMapEl.value, {
backgroundColor: null,
scale: 1.5
});
这个方案是测试时偶然发现的,具体原因不知。
2.2.2 动态样式
通过多次测试,发现是因为box-shadow导致的,因此可以通过在截图时关闭相应的标签box-shadow来解决:
<div class="node" :style="{ boxShadow: isScreenshot ? 'none' : '1px 1px 2px black' }"></div>
根据官方文档所说的,某些css样式html2Canvas是不支持的:
所以你用到了如上的css,尽量不要使用,如果非要用,可以与我一样,在截图时关闭,展示时开启,但会导致截图上无法展示相应的css。
2.2.3 强制添加阴影截图
虽然无法使用css样式阴影,但如果非要添加阴影并支持截图,其实可以使用其他方式实现。本案例推荐svg来添加阴影,如若使用svg,需要将svg或者需要添加的阴影的标签样式改为绝对坐标:
position: absolute;
将阴影覆盖在相应的标签后方,即可实现阴影展示并且在截图后保持样式:
svg的样例代码:
<!--width height 画布或者标签的大小-->
<svg :width="width" :height="height" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="f1" x="0" y="0" width="200%" height="200%">
<feDropShadow dx="2" dy="2" stdDeviation="5" flood-color="rgb(138, 138, 138)" flood-opacity="0.6" />
</filter>
</defs>
<!--x y 需要阴影的标签绝对坐标 elWidth elHeight 需要阴影的标签大小 elBorderEadius 需要阴影的标签若有圆角,改为圆角-->
<rect :x="x" :y="y" :width="elWidth" :height="elHeight" stroke="none"
stroke-width="0" fill="#000000" :rx="elBorderEadius" filter="url(#f1)" />
</svg>
三、总结
还有许多问题,还没遇到的在这篇文章就不阐述了,如若未来遇到,还会在这篇文章中继续更新。总的来说,html2Canvas使用起来非常简单,但问题也是不少,特别是看到生成的图片与预期不符,是非常糟心的,本文中通过动态css的开启与关闭其实可以解决非常多的问题,加以应用应该能获得预期效果。