文章目录
1. 背景介绍
背景:今年接到一个前端需求,将页面上的某些元素或者整个页面转换成图片格式,并允许用户下载。通过查阅资料,了解到,前端可用来导出图片的库有html2canvas、html-to-image等。另外,还可以通过canvas和svg绘制想要的效果,通过canvas和svg将其上的内容导出为本地图片。
综合了解比较后,我使用了html2canvas库将页面转化为图片格式,并允许用户下载为图片。
2. 版本介绍
前端框架:vue("v 3.0.0”),导出图片:html2canvas("v 1.4.1”)
vue2和vue3语法上会有些不同,Echarts版本影响不大
3. html2canvas导出图片步骤
3.1、解析DOM结构
html2canvas 首先会解析你指定的DOM元素,包括它的所有子元素。它会读取这些元素的样式、位置、内容等信息。
3.2、计算样式
库会计算每个元素的样式,包括应用的CSS规则、层叠样式、伪元素等。这通常涉及到样式的重新计算和布局的确定。(html2canvas并不是支持所有的css样式,我了解到的不支持box-shadow属性)
3.3、渲染到canvas
一旦计算出所有元素的样式,html2canvas 会创建一个临时的canvas元素,并开始在canvas上绘制DOM元素的视觉表示。这包括文本、颜色、图像、边框、阴影等。
3.4、处理图像
如果DOM中包含图片,html2canvas 需要等待这些图片加载完成。一旦图片加载完毕,它们就会被绘制到canvas上。这个过程中可能会涉及到跨域问题的处理,因为canvas对跨域图像有安全限制。
3.5、绘制完成
当所有元素都被绘制到canvas上后,html2canvas 会提供一个canvas元素的引用,你可以将其转换为图片或者进行其他操作。
3.6、导出图片
通常,我们会使用canvas的toDataURL方法将canvas内容转换为Base64编码的图片数据,然后可以通过创建一个a标签并模拟点击来实现图片的下载。
4. html2canvas使用介绍
// 使用html2canvas进行截图 ,第一个元素element为想要导出为图片的dom元素,第二个属性为一个配置对象,定义canvas的一些属性,下面列出一些常用的属性介绍,其他相关属性,可自行了解 ,其中我最常使用的就是scale属性
html2canvas(element,{
width:600, // canvas宽度,默认为元素element宽度
height:800, // canvas高度,默认为元素element高度
x:0, // 裁剪画布x坐标
y:0, // 裁剪画布y坐标
scrollX:0, // 渲染元素时x轴滚动的距离
scrollY:0, // 渲染元素时Y轴滚动的距离
scale:2, // 缩放比例,默认为浏览器设备像素比
useCORS:false, // 尝试使用CORS从服务器加载图像
imageTimeout:500, // 加载图像的超时时间(毫秒),设置为0可禁用超时,
ignoreElements: (element) => false // 渲染忽略元素,
onclone:() => {} // 函数类型,在这里你可以操作生成canvas的dom的节点,不影响原始dom节点
removeContainer:true // 布尔值,默认为true, 是否清理临时dom节点,
}).then(canvas => {
// 将canvas转换为图片并下载 ,url为base64格式的图片地址
let url = canvas.toDataURL("image/png");
});
}
5. 导出图片功能实现
5.1、主要代码
function captureContentWithScroll(element) {
const originalOverflow = element.style.overflow; // 保存原始overflow样式
const originalHeight = element.style.height; // 保存原始height样式
// 临时禁用滚动条并展开内容高度
element.style.overflow = 'hidden'; // 隐藏滚动条
element.style.height = 'auto'; // 展开内容区域以包含所有内容
// 使用html2canvas进行截图
html2canvas(element,{
scale:2
}).then(canvas => {
// 将canvas转换为图片并下载
let url = canvas.toDataURL("image/png");
downloadFile(exportFileName.value, url);
// 恢复原始样式
element.style.overflow = originalOverflow;
element.style.height = originalHeight;
});
}
// 点击下载图片
function downloadFile(fileName, content) {
let aLink = document.createElement("a");
let blob = base64ToBlob(content); //new Blob([content]);
let evt = document.createEvent("HTMLEvents");
evt.initEvent("click", true, true); //initEvent 不加后两个参数在FF下会报错 事件类型,是否冒泡,是否阻止浏览器的默认行为
aLink.download = fileName;
aLink.href = URL.createObjectURL(blob);
aLink.dispatchEvent(
new MouseEvent("click", { bubbles: true, cancelable: true, view: window })
); //兼容火狐
dialogVisible.value = false
}
function base64ToBlob(code) {
let parts = code.split(";base64,");
let contentType = parts[0].split(":")[1];
let raw = window.atob(parts[1]);
let rawLength = raw.length;
let uInt8Array = new Uint8Array(rawLength);
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], { type: contentType });
}
5.2、遇到问题与解决
问题:图片清晰度问题
解决:想要图片更清晰,可以增大scale值