如何在图片上添加水印?
1、把图片或者图片文件转成image元素
2、把转成的image转成canvas
3、在生成的canvas中添加水印

先看效果

js 给图片添加水印-LMLPHP
 

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)

注意:有些图片会报跨域问题这个服务器中配置处理跨域,这里不多解释

06-13 02:23