js 给图片添加水印

文章详细介绍了如何通过JavaScript将图片转换为image元素,再转为canvas,然后在canvas上添加水印文字,包括文字的字体、颜色、旋转角度等参数,并最终将处理后的图片保存为新的文件。提供的代码示例展示了完整的处理流程,包括从URL或图片文件创建image对象,到生成带水印的新图片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


如何在图片上添加水印?
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 = -25
) {

    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;
        img.width = document.body.clientWidth
        img.objectFit = 'contain'
    })
}

// 图片文件转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;
            img.width = document.body.clientWidth
        })
        reader.readAsDataURL(blob);
    })
}

// 图片转canvas
function imgToCanvas(img) {
    const canvas = document.createElement('canvas');
    console.log(img)
    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 = -1; i < canvas.width; i += (textWidth + (textWidth / 5))) {
            for (let j = 0; j < canvas.height * 4; j += 100) {
                // 填充文字,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)

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

JavaScript 中,给图片添加水印通常涉及到操作 HTML 元素以及使用 Canvas API。以下是一个简单的步骤和示例代码来实现这个功能: 1. 首先,你需要获取要添加水印图片元素(通常是 `img` 标签)和一个用于显示水印的文字元素(比如 `div`)。 ```javascript const imgElement = document.getElementById('image'); const watermarkElement = document.getElementById('watermark-text'); ``` 2. 创建一个 canvas 元素,设置其宽度和高度等于图片的尺寸,然后将其转换为 ImageData 对象以便进行处理。 ```javascript const canvas = document.createElement('canvas'); canvas.width = imgElement.naturalWidth; canvas.height = imgElement.naturalHeight; const ctx = canvas.getContext('2d'); ctx.drawImage(imgElement, 0, 0); const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); ``` 3. 接下来,在 canvas 上绘制水印文字。你可以调整字体大小、颜色和位置以适应图片。这里假设水印位于右下角: ```javascript const fontColor = 'rgba(255, 255, 255, 0.8)'; const fontSize = 20; // 可以根据需求调整 // 获取文字的大小 const textMetrics = ctx.measureText(watermarkElement.innerText); const textWidth = textMetrics.width; const textHeight = fontSize; // 计算水印位置 const x = canvas.width - textWidth - 10; // 偏移量可以根据喜好调整 const y = canvas.height - textHeight - 10; // 绘制水印 ctx.font = `${fontSize}px Arial`; ctx.fillStyle = fontColor; ctx.fillText(watermarkElement.innerText, x, y); ``` 4. 将处理后的 ImageData 重新应用到原 canvas 上,然后创建一个新的 `img` 元素来显示带有水印的图像。 ```javascript ctx.putImageData(imageData, 0, 0); // 创建新的 img 元素 const watermarkedImage = new Image(); watermarkedImage.src = canvas.toDataURL(); // 将水印后的图片插入到 DOM document.body.appendChild(watermarkedImage); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值