import { addWatermark } from '@/utils/common/WatermarkHelper';
/**
* 上传前校验
*/
function beforeUpload(file, files) {
let fileType = file.type;
if (fileType.indexOf('image') < 0) {
createMessage.info('请上传图片');
return false;
}
let num = uploadFileList.value.length + files.length;
if (num > props['fileMax']) {
createMessage.info('图片超出可上传个数');
return false;
}
if (props.isWatermark) {
return addWatermark(file, {}, props.url) // 关键代码
.then((watermarkedFile) => {
// 将处理后的图片加入到文件列表中
files.push({
...file,
status: 'done', // 设置状态为已完成
url: URL.createObjectURL(watermarkedFile) // 使用 ObjectURL 作为临时展示
});
return watermarkedFile;
})
.catch((error) => {
console.error('Error adding watermark:', error);
});
}
}
addWatermark 组件
import bgCanvas from '@/assets/images/bgCanvas.png';
import bgCanvasCode from '@/assets/images/bgCanvasCode.png';
import QRCode from 'qrcode';
import dayjs from 'dayjs';
interface TextWatermark {
content: string;
fontSize?: number;
color?: string;
x?: number;
y?: number;
type?: string;
}
interface ImageWatermark {
url: string;
x?: number;
y?: number;
width?: number;
height?: number;
type?: string;
}
interface WatermarkOptions {
texts?: TextWatermark[];
images?: ImageWatermark[];
}
function generateQRCode(url: string): Promise<string> {
return QRCode.toDataURL(url, { width: 128, margin: 1 }).then((dataURL) => {
const img = new Image();
img.src = dataURL;
return new Promise((resolve) => {
img.onload = () => resolve(dataURL);
});
});
}
export const addWatermark = (file: File, options: WatermarkOptions, url: string): Promise<File> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
const img = new Image();
img.src = e.target?.result as string;
img.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
if (!ctx) {
reject(new Error('Failed to get canvas context'));
return;
}
// 设置画布尺寸与底图相同
// canvas.width = 1080 || 1920
// canvas.height = 1920 || 1080
canvas.width = img.width;
canvas.height = img.height;
const scaleX = img.width > 1080 ? img.width / 1080 : 1;
const scaleY = img.height > 1920 ? img.height / 1080 : 1;
const scale = scaleX > scaleY ? scaleX : scaleY;
// 禁用图像平滑处理,防止模糊
ctx.imageSmoothingEnabled = false;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// 如果没有提供图片水印,则使用默认图片
generateQRCode(url).then((qrcodeImage) => {
let images: ImageWatermark[] = [
{ url: bgCanvas, x: 0, y: 0, width: 230 * scale, height: 68.5 * scale },
{ url: bgCanvasCode, x: canvas.width - 138 * scale, y: canvas.height - 160 * scale, width: 128 * scale, height: 150 * scale },
{ url: qrcodeImage, x: canvas.width - 124 * scale, y: canvas.height - 120 * scale, width: 100 * scale, height: 100 * scale }
];
if (options?.images) images.push(...options.images);
let loadedImages = 0;
const totalImages = images.length;
const imageElements: HTMLImageElement[] = [];
images.forEach((imageOptions, index) => {
const watermarkImg = new Image();
watermarkImg.src = imageOptions.url;
watermarkImg.onload = () => {
imageElements[index] = watermarkImg;
loadedImages++;
if (loadedImages === totalImages) {
imageElements.forEach((watermarkImg, i) => {
const { x = canvas.width - watermarkImg.width, y = canvas.height - watermarkImg.height, width = watermarkImg.width, height = watermarkImg.height, type } = images[i];
ctx.drawImage(watermarkImg, x, y, width, height);
});
canvas.toBlob((blob) => {
if (blob) {
const watermarkedFile = new File([blob], file.name, { type: 'image/png' }); // 使用 PNG 格式以保留质量
resolve(watermarkedFile);
} else {
reject(new Error('Failed to convert canvas to blob'));
}
}, 'image/png'); // 确保使用 PNG 格式,以避免图像质量损失
}
};
watermarkImg.onerror = () => {
reject(new Error('Failed to load watermark image'));
};
});
});
// 文字添加
const texts = options.texts?.length ? options.texts : [{ content: dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss'), fontSize: 12 * scale, color: 'rgba(255, 255, 255, 1)', x: 110 * scale, y: 30 * scale }];
texts.forEach((text) => {
const { content, fontSize = Math.max(canvas.width, canvas.height) * 0.05, color = 'rgba(255, 255, 255, 1)', x = canvas.width * 0.02, y = canvas.height * 0.02 } = text;
ctx.font = `${fontSize}px Arial`;
ctx.fillStyle = color;
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillText(content, x, y);
});
};
img.onerror = () => {
reject(new Error('Failed to load image'));
};
};
reader.onerror = () => {
reject(new Error('Failed to read file'));
};
reader.readAsDataURL(file);
});
};
vue 在图片上传时进行图片二维码、文字等水印生成并上传文字
最新推荐文章于 2024-11-11 23:32:58 发布