项目中经常会遇到给图片增加水印的需求,这里我用到了Ant Design Vue框架,1.x和3.x加水印的方式差不多,都是返回Promise对象,只是写法上有所差别,那让我们具体看看怎么实现吧
一、1.x版本(适用Vue2)
1.x版本的ant-design-vue使用transformFile来转换上传的文件,所以我们vue2使用transformFile来给图片添加水印
<template>
<div>
<!-- action写自己的上传接口 -->
<a-upload
:defaultFileList="fileList"
action="xxxx"
:transform-file="transformFile">
<div style="margin-top: 8px">Upload</div>
</a-upload>
</div>
</template>
<script>
export default {
data() {
return {
fileList: []
}
},
methods: {
transformFile(file) {//添加水印
return new Promise(resolve => {
const reader = new FileReader();
reader.readAsDataURL(file);//file转base64
reader.onload = (e) => {
const canvas = document.createElement('canvas');
const img = new Image()
img.src = e.target.result;
img.onload = () => {
let ctx = canvas.getContext('2d');
let data = ""
let imgWidth = img.width;
let imgHeight = img.height;
let fontsize = imgWidth > imgHeight ? imgHeight / 10 : imgWidth / 10//设定文字大小随图片大小变化
canvas.width = imgWidth;//画布宽度
canvas.height = imgHeight;//画布高度
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);//绘制图片大小和先前图片一致
ctx.fillStyle = 'rgb(96,96,96,0.1)';//水印颜色,透明度
ctx.textBaseline = 'top';//水印对其的基准线
ctx.font = `${fontsize}px Verdana`//文字大小
ctx.fillText('Ant Design Vue', 20, 20);//添加的文字
data = canvas.toDataURL(file.type); //输出压缩后的base64
//base64转file
let arr = data.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
let files = new File([new Blob([u8arr], { type: mime })], file.name, { type: file.type })
files.uid = file.uid
resolve(files)
};
};
})
}
}
}
</script>
二、3.x版本(适用Vue3)
3.x版本的ant-design-vue使用beforeUpload来转换上传的文件,所以我们vue3使用beforeUpload来给图片添加水印
<template>
<div>
<!-- action写自己的上传接口 -->
<a-upload
v-model:file-list="fileList"
action="xxx"
list-type="picture-card"
:before-upload="beforeUpload"
>
<plus-outlined />
<div style="margin-top: 8px">Upload</div>
</a-upload>
</div>
</template>
<script setup lang="ts">
import type {UploadProps} from 'ant-design-vue';
import { ref } from 'vue';
const fileList = ref<UploadProps['fileList']>([])
let beforeUpload: UploadProps['beforeUpload'] = file => {//添加水印
return new Promise(resolve => {
const reader = new FileReader();
reader.readAsDataURL(file);//file转base64
reader.onload = (e) => {
const canvas = document.createElement('canvas');
const img = new Image();
img.src = e.target.result;
img.onload = () => {
let ctx = canvas.getContext('2d');
let data = "";
let imgWidth = img.width;
let imgHeight = img.height;
let fontsize = imgWidth > imgHeight ? imgHeight / 10 : imgWidth / 10;//设定文字大小随图片大小变化
canvas.width = imgWidth;//画布宽度
canvas.height = imgHeight;//画布高度
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);//绘制图片大小和先前图片一致
ctx.fillStyle = 'rgb(96,96,96,0.1)';//水印颜色,透明度
ctx.textBaseline = 'top';//水印对其的基准线
ctx.font = `${fontsize}px Verdana`;//文字大小
ctx.fillText('Ant Design Vue', 20, 20);//添加的文字
data = canvas.toDataURL(file.type); //输出压缩后的base64
//base64转file
let arr = data.split(',');
let mime = arr[0].match(/:(.*?);/)[1];
let bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
let files = new File([new Blob([u8arr], { type: mime })], file.name, { type: file.type });
files.uid = file.uid;
resolve(files);
}
}
})
}
</script>
三、水印效果
原图:
加水印后的图片: