一、需求提出
前端实现给一张图片加图片水印,使用eel-image-viewer组件展示加过水印的图片,可用于单张图片下载和批量下载压缩成一个压缩包。
<template>
<el-image-viewer
v-if="showPreview"
:urlList="srcList"
>
</el-image-viewer>
</template>
二、方法实现
使用canvas实现上述加水印需求。方法入参为两张图片的URL,其中一张图片为原始图片,一张为水印图片,最终得到一个新的blob文件的URL。可以根据自己的需求对生成的URL做一些操作。
三、方法源码
generateWatermarkImage方法为水印绘制方法,dataURLtoBlob方法用于将canvas对象生成的base64文件格式转换成blob对象,然后转成blob开头的URL
generateWatermarkImage(originalImageUrl, watermarkImageUrl) {
// 创建一个Image对象用于加载原始图片和水印图片
const originalImage = new Image();
originalImage.setAttribute("crossOrigin", "anonymous"); //关键,防止canvas跨域污染
const watermarkImage = new Image();
watermarkImage.setAttribute("crossOrigin", "anonymous"); //关键
// 监听原始图片加载完成事件
originalImage.onload = () => {
// 创建一个canvas元素用于绘制图片
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
// 设置canvas的大小为原始图片的大小
canvas.width = originalImage.width;
canvas.height = originalImage.height;
// 绘制原始图片
context.drawImage(originalImage, 0, 0);
// 绘制水印图片在左下角
context.drawImage(
watermarkImage,
30,
canvas.height - watermarkImage.height - 30
);
// 将canvas转换为DataURL
const watermarkImageUrl = canvas.toDataURL("image/png");
// 生成新的图片链接
const newImageUrl = URL.createObjectURL(
this.dataURLtoBlob(watermarkImageUrl)
);
// 在控制台打印新的图片链接
// console.log("newImageUrl", newImageUrl);
};
// 加载原始图片和水印图片
originalImage.src = originalImageUrl;
watermarkImage.src = watermarkImageUrl;
},
// 将DataURL转换为Blob对象
dataURLtoBlob(dataURL) {
const arr = dataURL.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 });
},
四、注意事项
1、如果图片的来源的域名和当前网址的域名不一样,需要加上以下 代码:
originalImage.setAttribute("crossOrigin", "anonymous");
这是因为浏览器的同源策略。当一个网页尝试加载来自其他域的图片资源时,浏览器会执行同源策略的检查。如果图片资源的域名、协议或端口与当前网页的域名、协议或端口不完全匹配,浏览器就会阻止页面对该图片资源的访问。