如何在图片上添加水印?
1、把图片或者图片文件转成image元素
2、把转成的image转成canvas
3、在生成的canvas中添加水印
先看效果
1、把图片或者图片文件转成image元素
function urlToImg(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.addEventListener('load', () => resolve(img));
img.crossOrigin = 'Anonymous';
img.src = url;
})
}
function blobToImg(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.addEventListener('load', () => {
const img = new Image();
img.addEventListener('load', () => resolve(img));
img.crossOrigin = 'Anonymous';
img.src = reader.result;
})
reader.readAsDataURL(blob);
})
}
2、把转成的image转成canvas
function imgToCanvas(img) {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
return canvas;
}
3、在生成的canvas中添加水印
function watermark(canvas, text, font, fillStyle, rotate) {
return new Promise((resolve, reject) => {
let context = canvas.getContext('2d');
context.font = font;
context.fillStyle = fillStyle;
context.rotate(rotate * Math.PI / 180);
context.textAlign = 'center';
context.textBaseline = 'Middle';
const textWidth = context.measureText(text).width;
for (let i = (canvas.height * 0.5) * -1; i < 800; i += (textWidth + (textWidth / 5))) {
for (let j = 0; j < canvas.height * 1.5; j += 128) {
// 填充文字,i 间距, j 间距
context.fillText(text, i, j);
}
}
canvas.toBlob((blob) => resolve(blob));
})
}
base64转图片文件
function base64ToFile(dataurl, filename = 'image.png') {
if (!dataurl) {
return '';
}
let arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type: mime});
}
生成水印图片
/**
*
* @param {File | String} image 图片文件或图片url地址
* @param {String} text 水印文字
* @param {String} font 字体属性
* @param {String} fillStyle 字体颜色
* @param {Number} rotate 旋转角度
*/
export async function addWaterMark(
image,
text = `井底的蜗牛 1234567890 ${getCurDay().year}-${getCurDay().month}-${getCurDay().date}`,
font = '16px microsoft yahei',
fillStyle = 'rgba(0, 0, 0, 0.3)',
rotate = -45
) {
let img;
if (typeof (image) === 'string') {
img = await urlToImg(image);
} else {
if (['image/png', 'image/jpeg'].includes(image.type)) {
img = await blobToImg(image);
} else {
return Promise.reject('不支持该类型的文件加水印');
}
}
let canvas = imgToCanvas(img);
let blob = await watermark(canvas, text, font, fillStyle, rotate);
let newImg = await blobToImg(blob);
let src = newImg.src;
let newFile = base64ToFile(src, 'image.png');
let newUrl = window.URL.createObjectURL(newFile);
return {newFile, src, newUrl};
}
完整代码
/**
*
* @param {File | String} image 图片文件或图片url地址
* @param {String} text 水印文字
* @param {String} font 字体属性
* @param {String} fillStyle 字体颜色
* @param {Number} rotate 旋转角度
*/
export async function addWaterMark(
image,
text = `井底的蜗牛 1234567890 ${getCurDay().year}-${getCurDay().month}-${getCurDay().date}`,
font = '16px microsoft yahei',
fillStyle = 'rgba(0, 0, 0, 0.3)',
rotate = -45
) {
let img;
if (typeof (image) === 'string') {
img = await urlToImg(image);
} else {
if (['image/png', 'image/jpeg'].includes(image.type)) {
img = await blobToImg(image);
} else {
return Promise.reject('不支持该类型的文件加水印');
}
}
let canvas = imgToCanvas(img);
let blob = await watermark(canvas, text, font, fillStyle, rotate);
let newImg = await blobToImg(blob);
let src = newImg.src;
let newFile = base64ToFile(src, 'image.png');
let newUrl = window.URL.createObjectURL(newFile);
return {newFile, src, newUrl};
}
// 图片地址转image
function urlToImg(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.addEventListener('load', () => resolve(img));
img.crossOrigin = 'Anonymous';
img.src = url;
})
}
// 图片文件转image
function blobToImg(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.addEventListener('load', () => {
const img = new Image();
img.addEventListener('load', () => resolve(img));
img.crossOrigin = 'Anonymous';
img.src = reader.result;
})
reader.readAsDataURL(blob);
})
}
// 图片转canvas
function imgToCanvas(img) {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
return canvas;
}
function base64ToFile(dataurl, filename = 'image.png') {
if (!dataurl) {
return '';
}
let arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type: mime});
}
// canvas 添加水印
function watermark(canvas, text, font, fillStyle, rotate) {
return new Promise((resolve, reject) => {
let context = canvas.getContext('2d');
context.font = font;
context.fillStyle = fillStyle;
context.rotate(rotate * Math.PI / 180);
context.textAlign = 'center';
context.textBaseline = 'Middle';
const textWidth = context.measureText(text).width;
for (let i = (canvas.height * 0.5) * -1; i < 800; i += (textWidth + (textWidth / 5))) {
for (let j = 0; j < canvas.height * 1.5; j += 128) {
// 填充文字,i 间距, j 间距
context.fillText(text, i, j);
}
}
canvas.toBlob((blob) => resolve(blob));
})
}
function getCurDay() {
var datetime = new Date();
var year = datetime.getFullYear();
var month = datetime.getMonth() + 1 < 10 ? "0" + (datetime.getMonth() + 1) : datetime.getMonth() + 1;
var date = datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();
return {
year,
month,
date
}
}
调用方法
const res = await addWaterMark('https://images.modao.cc/images/images-2021/landingpage/design/bottom-section-bg-1.svg');
console.log(res)
注意:有些图片会报跨域问题这个服务器中配置处理跨域,这里不多解释