需求:点击下载可以导出组件的截图及数据信息文件
分析:前端生成组件截图,带着其他参数传给后端,拿到excel文件并下载。关键在于生成组件的截图,这里通过html2canvas插件来实现。
npm install html2canvas
import html2canvas from 'html2canvas'
//下载图标,绑定下载事件
<i class="el-icon-download" style="cursor: pointer;" @click="download">i>
//需要生成截图的部分
<div class='wrapper' ref='screen'>
...
div>
download() {
//el的全局loading,根据需求,可加可不加,在下载完成时或请求完成时用 loading.close()关闭
const loading = this.$loading({
lock: true,
text: '文件下载中',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.8)'
});
html2canvas(this.$refs.screen, {
backgroundColor: null,//画布背景色(如果未在DOM中指定)。设置null为透明
useCORS: true, //允许跨域
scale: 1 //用于渲染的比例
}).then((canvas) => {
// 此时已经生成我们想要的截图,可以下载查看
const url = canvas.toDataURL('image/png') //转图片链接,为图片的base64形式
const a = document.createElement('a')
const event = new MouseEvent('click')
a.download = '图片'
a.href = url
a.dispatchEvent(event)
loading.close()
// 转为png格式文件格式传以给后端
// formData即为我们要传的内容,如果还有其他参数要传输可以通过formData.append('key',value)来添加
const formData = new FormData()
canvas.toBlob(function(blob) {
formData.append('image', blob, 'image.png')
})
})
},
因为项目的图片资源是托管在另一个平台上,在生成截图时,原有dom的图片由于跨域 canvas “被污染”,一直无法生成,尝试了多种办法,设置useCORS: true且给img标签设crossorigin="anonymous"也无法解决。最后找到两种解决方案:一种是把图片转为编码格式base64,此方法可以纯前端解决该问题,另一种是修改服务端的配置来解决跨域问题。采用的是第一种方案,附上转base64的方法。(但这种方法也会有代码冗余体积增大,可读性降低等缺点)
imgUrlToBase64(imgUrl) {
const image = new Image();
image.setAttribute('crossOrigin', 'anonymous');
const imageUrl = imgUrl;
image.src = imageUrl
// image.onload为异步加载
image.onload = () => {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0, image.width, image.height);
var quality = 0.8;
const dataurl = canvas.toDataURL('image/png', quality);
console.log(dataurl, 'dataurl64')
}
},
html2canvas的屏幕截图是基于 DOM 的,不会生成实际的屏幕截图,而是基于页面上可用的信息构建屏幕截图,html2canvas库对以下样式可能无效或不完全支持:
由于html2canvas这个插件在生成截图的时候有很多弊端,在canvas绘制时耗时长,且绘制时屏幕会阻塞无法操作,后续截图选择了其他方案,使用domtoimage发现丝滑很多,可参考文章使用domtoimage生成截图。