HTML5的Canvas画布提供了丰富的图形和文本绘制能力,我们可以通过它读取原始图片,在图片上绘制文字,最终生成带有文字水印的新图片,整个过程不需要依赖第三方库,兼容性也比较好。

基础实现步骤
给图片添加文字水印的核心流程分为四步:创建Canvas元素、加载原始图片、绘制图片到Canvas、在Canvas上绘制文字水印,最后导出带水印的图片。下面是完整的实现代码:
// 获取Canvas元素和上下文
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 创建图片对象
const img = new Image();
// 允许跨域加载图片,避免画布污染无法导出
img.crossOrigin = 'anonymous';
img.src = 'https://picsum.photos/600/400?random=2';
img.onload = function() {
// 设置Canvas尺寸和原始图片一致
canvas.width = img.width;
canvas.height = img.height;
// 绘制原始图片到Canvas
ctx.drawImage(img, 0, 0, img.width, img.height);
// 设置水印文字样式
ctx.font = '30px Microsoft YaHei';
ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
ctx.textAlign = 'right';
ctx.textBaseline = 'bottom';
// 绘制水印文字,位置在右下角
const watermarkText = '示例水印';
ctx.fillText(watermarkText, canvas.width - 20, canvas.height - 20);
// 导出带水印的图片,转为base64格式
const watermarkedImageUrl = canvas.toDataURL('image/png');
console.log('带水印的图片地址:', watermarkedImageUrl);
// 可以在页面上展示带水印的图片
const resultImg = document.createElement('img');
resultImg.src = watermarkedImageUrl;
document.body.appendChild(resultImg);
};
img.onerror = function() {
console.error('图片加载失败,请检查图片地址是否正确');
};
水印样式调整方法
我们可以通过修改Canvas的上下文属性,调整水印的显示效果,满足不同的需求:
- 调整水印颜色和不透明度:通过
fillStyle属性设置,比如rgba(0, 0, 0, 0.3)表示黑色半透明水印 - 调整水印字体:通过
font属性设置,格式和CSS的font属性一致,比如24px SimSun表示24像素的宋体 - 调整水印位置:修改
fillText方法的前两个参数,分别是文字的x坐标和y坐标,也可以结合textAlign和textBaseline调整对齐方式 - 添加水印旋转效果:使用
rotate方法旋转画布,再绘制文字,实现倾斜水印
倾斜水印实现示例
下面是给图片添加倾斜重复水印的代码,水印会铺满整个图片:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.crossOrigin = 'anonymous';
img.src = 'https://picsum.photos/600/400?random=3';
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
// 设置水印样式
ctx.font = '20px Microsoft YaHei';
ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
// 设置文字旋转角度,单位是弧度,45度对应Math.PI/4
ctx.rotate(-Math.PI / 4);
// 重复绘制水印,覆盖整个画布
const watermarkText = 'ipipp.com';
const step = 150; // 水印之间的间距
for (let x = -canvas.height; x < canvas.width + canvas.height; x += step) {
for (let y = -canvas.width; y < canvas.height + canvas.width; y += step) {
ctx.fillText(watermarkText, x, y);
}
}
// 导出结果
const resultUrl = canvas.toDataURL('image/png');
console.log('倾斜水印图片地址:', resultUrl);
};
注意事项
在实际使用过程中,有几个需要注意的点:
- 如果加载的图片是跨域资源,必须设置
img.crossOrigin = 'anonymous',否则Canvas会被标记为污染状态,无法调用toDataURL方法导出图片 - 水印文字的位置和对齐方式需要根据图片尺寸动态调整,避免水印超出图片范围
- 如果需要处理大量图片的水印,建议封装成通用函数,减少重复代码
- 导出的图片默认是png格式,如果需要其他格式,可以修改
toDataURL的第一个参数,比如image/jpeg
通用水印函数封装
我们可以把添加水印的逻辑封装成一个通用函数,方便在不同场景调用:
/**
* 给图片添加文字水印
* @param {string} imageUrl 原始图片地址
* @param {string} text 水印文字
* @param {Object} options 水印配置,可选
* @param {string} options.font 字体样式,默认20px Microsoft YaHei
* @param {string} options.color 文字颜色,默认rgba(255,255,255,0.5)
* @param {number} options.x 水印x坐标,默认图片宽度-20
* @param {number} options.y 水印y坐标,默认图片高度-20
* @returns {Promise<string>} 带水印的图片base64地址
*/
function addTextWatermark(imageUrl, text, options = {}) {
return new Promise((resolve, reject) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.crossOrigin = 'anonymous';
img.src = imageUrl;
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
// 合并默认配置和用户配置
const config = {
font: '20px Microsoft YaHei',
color: 'rgba(255, 255, 255, 0.5)',
x: canvas.width - 20,
y: canvas.height - 20,
...options
};
ctx.font = config.font;
ctx.fillStyle = config.color;
ctx.textAlign = 'right';
ctx.textBaseline = 'bottom';
ctx.fillText(text, config.x, config.y);
resolve(canvas.toDataURL('image/png'));
};
img.onerror = function() {
reject(new Error('图片加载失败'));
};
});
}
// 调用示例
addTextWatermark('https://picsum.photos/600/400?random=4', '版权所有')
.then(url => {
console.log('带水印的图片地址:', url);
})
.catch(err => {
console.error(err);
});