封装URL.createObjectURL加水印的函数
以下是一个封装好的函数,可以为通过URL.createObjectURL
创建的URL对象添加水印:
/**
* 创建带水印的对象URL
* @param {Blob|MediaSource} blob - 原始Blob对象
* @param {Object} options - 配置选项
* @param {string} [options.text='Watermark'] - 水印文字
* @param {string} [options.color='rgba(180, 180, 180, 0.5)'] - 水印颜色
* @param {string} [options.font='16px Arial'] - 水印字体
* @param {number} [options.rotate=-20] - 水印旋转角度
* @param {number} [options.interval=100] - 水印间隔
* @returns {Promise<string>} 带水印的对象URL
*/
async function createObjectURLWithWatermark(blob, options = {}) {
// 默认配置
const {
text = 'Watermark',
color = 'rgba(180, 180, 180, 0.5)',
font = '16px Arial',
rotate = -20,
interval = 100
} = options;
// 如果是图片类型
if (blob.type.startsWith('image/')) {
return createImageWatermark(blob, { text, color, font, rotate, interval });
}
// 如果是视频类型
if (blob.type.startsWith('video/')) {
return createVideoWatermark(blob, { text, color, font });
}
// 其他类型直接返回原始URL
return URL.createObjectURL(blob);
}
/**
* 为图片添加水印
*/
async function createImageWatermark(blob, options) {
const { text, color, font, rotate, interval } = options;
// 创建图片元素
const img = await blobToImage(blob);
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 设置画布大小与图片一致
canvas.width = img.width;
canvas.height = img.height;
// 绘制原始图片
ctx.drawImage(img, 0, 0, img.width, img.height);
// 设置水印样式
ctx.fillStyle = color;
ctx.font = font;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate(rotate * Math.PI / 180);
// 绘制水印
for (let x = -canvas.width; x < canvas.width * 2; x += interval) {
for (let y = -canvas.height; y < canvas.height * 2; y += interval) {
ctx.fillText(text, x, y);
}
}
// 转换回Blob并创建URL
return new Promise((resolve) => {
canvas.toBlob((watermarkedBlob) => {
resolve(URL.createObjectURL(watermarkedBlob));
}, blob.type);
});
}
/**
* 为视频添加水印(简单实现,实际需要更复杂的处理)
*/
async function createVideoWatermark(blob, options) {
// 注意:实际视频水印需要更复杂的处理,这里只是简单示例
const videoUrl = URL.createObjectURL(blob);
return videoUrl;
}
/**
* 将Blob转换为Image对象
*/
function blobToImage(blob) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = URL.createObjectURL(blob);
});
}
// 导出函数
export default createObjectURLWithWatermark;
使用示例
// 对于图片文件
const fileInput = document.getElementById('file-input');
fileInput.addEventListener('change', async (e) => {
const file = e.target.files[0];
if (file) {
const watermarkedUrl = await createObjectURLWithWatermark(file, {
text: '机密文件',
color: 'rgba(255, 0, 0, 0.5)',
font: '20px Arial',
rotate: -30,
interval: 150
});
// 使用带水印的URL
const img = document.createElement('img');
img.src = watermarkedUrl;
document.body.appendChild(img);
}
});
注意事项
- 视频水印的实现比较复杂,上面的示例只是一个简单框架,实际应用中可能需要使用WebGL或专门的视频处理库。
- 水印功能会增加处理时间,特别是对大文件。
- 使用完毕后,记得调用
URL.revokeObjectURL()
释放内存。 - 这种方法的水印在前端可以被移除,如需更安全的水印,应考虑在后端处理。
- 对于PDF等非图像文件,需要先转换为图像才能添加水印。