前言
1. 在前端开发中,海报的绘制、生成和下载是一个常见的需求,尤其是当我们需要将用户生成的内容或特定样式的网页部分保存为图片时。为实现这一目标,我们可以使用强大的 JavaScript 库 html2canvas
。该库允许我们将 HTML 元素转换为 Canvas 图像,从而生成并下载图片。
通过 html2canvas
,我们可以轻松捕获指定的 DOM 元素并将其渲染为 Canvas 图像,能够很好地处理复杂的样式和布局。这样一来,用户生成的内容或网页的特定部分可以以图像形式保存下来,实现了图形化的输出和下载功能。
htm2canvas本质是将页面的 DOM 结构和样式转换为图像,并支持各种自定义选项。
步骤
- 海报样式逻辑开发:在页面上将所需要的海报样式和逻辑在页面上进行开发实现。
- 捕获html元素:使用
html2canvas
捕获指定的 DOM 元素,并将其渲染到 Canvas 上。 - 生成图片数据:将canvas内容转为图片数据(会转为base64格式,默认png图片)。
- 触发下载:创建下载链接,模拟用户点击,触发下载功能。
功能实现
1. 生成海报
// 创建海报
createdCvs() {
window.loadingShow("加载中")
html2canvas(document.querySelector("#cvs-box"), // 获取需要截图的元素
// dpi越大,图片越清晰
{ width: 2079, height: 2953, allowTaint: true, useCORS: true, scale: 1, dpi: 1200 }).then(canvas => {
document.body.appendChild(canvas) // 创建canvas元素
const link = canvas.toDataURL()
const now = new Date();
const year = now.getFullYear(); // 年份
const month = now.getMonth() + 1; // 月份,getMonth() 返回的月份是从0开始的
const day = now.getDate(); // 日
const hours = now.getHours(); // 小时
const minutes = now.getMinutes(); // 分钟
const seconds = now.getSeconds(); // 秒
const name = `【宣传海报】${this.subName}-${year}年${month}月${day}日 ${hours}时${minutes}分${seconds}秒`
//
this.handleBeforeUpload(link, name)
this.exportPicture(link, name)
document.body.removeChild(canvas);
});
},
2.上传图片
handleBeforeUpload(link, name) {
// 将Base64字符串转换为Blob对象
const blob = this.base64ToBlob(link);
// 创建一个新的File对象用于上传
const newFile = new File([blob], name, { type: 'image/png' });
// 使用新的File对象进行上传
this.handleChange(newFile, name);
// 阻止默认上传行为
return false;
},
// 处理返回的数据,base64格式
base64ToBlob(base64Data) {
// 将base64的数据部分提取出来
const arr = base64Data.split(',');
const mime = arr[0].match(/:(.*?);/)[1];
const bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
},
// 图片上传
async handleChange(file, name) {
const action = {
fileName: name,
file: file
};
try {
// 上传
this.isUploading = true;
await checkSession()
this.$store.dispatch("customer/ossPosterUpload", action).then((res) => {
this.downloadPic(res.url, name)
this.isUploading = false;
}).catch(() => {
this.$message.error("上传失败");
this.isUploading = false;
});
} catch (e) {
this.isUploading = false;
} finally {
window.loadingHide()
}
},
3. 下载海报
// 导出图片
exportPicture(link, name = "未命名文件") {
const file = document.createElement("a");
file.style.display = "none";
file.href = link;
file.download = decodeURI(name);
document.body.appendChild(file);
file.click();
document.body.removeChild(file);
},
遇到的问题和解决方案
1.使用的背景图片下载后模糊
不去使用background-img放置图片,使用image标签放置背景图片,使用定位去放置元素
2.下载图片像素差
修改dpi参数,数值越大,图片体积越大,越清晰,(但是超过一定数量可能会变成下载txt文件)
3.下载图片不全缺少其他图片
涉及到了跨域问题,查阅资料有几种解决方法
- 在img标签上配置crossorigin: anonymous(但是我设置了还是有跨域问题)
- 在请求图片下载请求头中添加Access-Control-Allow-Origin:自己的项目地址(我使用的这种方法,通过运维去配置对应的域名)