<template>
<div class="upload-watermark">
<van-uploader
v-model="fileList"
:after-read="handleUpload"
:max-size="10 * 1024 * 1024"
:max-count="5"
:multiple="true"
accept="image/*"
:file-list="fileList"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { UploaderFileListItem } from "vant";
import dayjs from "dayjs";
const fileList = ref<UploaderFileListItem[]>([]); // 用于展示加水印后的文件列表
const handleUpload = (file: UploaderFileListItem | UploaderFileListItem[]) => {
const files = Array.isArray(file) ? file : [file]; // 确保无论是单文件还是多文件,`files` 都是数组
files.forEach((fileItem, index) => {
if (!fileItem.file) return; // 确保 fileItem.file 存在
const reader = new FileReader();
reader.onload = (e: ProgressEvent<FileReader>) => {
const image = new Image();
image.src = e.target?.result as string;
image.onload = () => {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
if (ctx) {
// 设置画布大小为图片大小
canvas.width = image.width;
canvas.height = image.height;
// 绘制上传的图片到画布
ctx.drawImage(image, 0, 0, image.width, image.height);
// 设置水印文本样式
const text = "水印文本";
const date = dayjs().format("YYYY-MM-DD HH:mm:ss");
ctx.font = "40px Arial";
ctx.fillStyle = "rgba(255, 255, 255, 0.3)";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
// 旋转角度和水印间隔设置
const angle = (30 * Math.PI) / 180; // 转换为弧度
const xOffset = 400; // 增大水平方向间隔
const yOffset = 300; // 增大垂直方向间隔
// 循环绘制水印,直到铺满整个画布
for (let x = -canvas.width; x < canvas.width * 2; x += xOffset) {
for (let y = -canvas.height; y < canvas.height * 2; y += yOffset) {
ctx.save();
ctx.translate(x, y);
ctx.rotate(angle);
// 绘制文本在上
ctx.fillText(text, 0, -20);
// 绘制时间在下
ctx.fillText(date, 0, 20);
ctx.restore();
}
}
// 将处理后的图片导出为 base64 字符串,并替换 fileList 中对应的文件
const watermarkedImage = canvas.toDataURL("image/jpeg");
// 将水印后的图片添加到 fileList,并移除原始文件
fileList.value = fileList.value.filter((item) => item !== fileItem); // 移除原始文件
fileList.value.push({
...fileItem,
url: watermarkedImage, // 使用加水印后的图片
});
}
};
};
reader.readAsDataURL(fileItem.file);
});
};
</script>
<style scoped lang="scss">
.upload-watermark {
margin-top: 20px;
display: flex;
flex-direction: column;
align-items: center;
}
</style>
效果图: