仅做记录。
话不多说没直接上代码和效果。
未添加水印前:
添加水印后:
代码:为了优化性能,底图只需要绘制一次,且导出canvas数据时也仅一次。当复合水印添加完成后再导出。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<img id="image_1" src="https://cdn.jsdelivr.net/gh/zhangpanfei/static@demo/img/test.jpg" alt=""
crossorigin="anonymous">
<button id="add">加水印</button>
</body>
</html>
<script>
const arr = ['image', 'red', 'orange', 'yellow', 'text'];
document.getElementById('add').addEventListener('click', () => {
const image_1 = document.getElementById('image_1');
waterMark(image_1)
});
async function waterMark(image) {
const canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
for (let index = 0; index < arr.length; index++) {
const element = arr[index];
if (element === 'image') {
await imageOnload(() => {
return new Promise((resolve) => {
const _img = new Image();
_img.crossOrigin = 'anonymous';
_img.width = 300;
_img.height = 300;
_img.src = 'https://cdn.jsdelivr.net/gh/zhangpanfei/static@demo/img/test.jpg'; // 模拟图片
_img.onload = () => {
ctx.save();
ctx.rotate((Math.PI / 180) * -10);
ctx.globalAlpha = 50 / 100; // 透明度设置
ctx.drawImage(_img, 50, 30, 100, 100);
ctx.restore();
resolve(true);
}
});
});
} else if (element === 'text') {
ctx.save();
ctx.rotate((Math.PI / 180) * 0);
ctx.fillStyle = 'blue';
ctx.fillText('才是是是是是是是是是是是是是', 400, 100);
ctx.restore();
} else {
ctx.save();
ctx.rotate((Math.PI / 180) * 0);
ctx.fillStyle = element;
ctx.fillRect(300, 80 * (index + 1), 70, 30);
ctx.fillText(index + 1, 300, 80 * (index + 1));
ctx.restore();
}
}
image.src = canvas.toDataURL('image/png');
}
async function imageOnload(fun) {
return new Promise(async (resolve) => {
const isOK = await fun();
if (isOK) {
resolve(isOK);
}
});
}
</script>