在数字化时代,保护原创图片版权变得日益重要。一个实用的图片水印工具可以让用户轻松地为自己的图片添加个性化的水印,从而有效防止未经授权的使用。这种工具不仅能够满足个人用户的版权保护需求,也适合企业对商业图片进行标记。通过自定义水印的文字内容、样式、位置和透明度等参数,用户可以在不影响原图质量的前提下,实现专业的版权保护效果。本文将介绍如何使用 HTML、CSS 和 JavaScript 实现一个图片水印工具。效果演示
这款图片水印工具提供了丰富的自定义选项,用户可以灵活调整水印的各项属性。图片上传后会显示在右侧预览区域。左侧控制面板提供了多个配置项:设置水印文字内容,选择不同的字体样式,调节字号大小,设定文字颜色和透明度,以及控制水印的旋转角度。此外,用户还能精确控制水印的位置,包括九宫格定位和微调偏移量,还可以选择是否启用平铺水印效果或添加描边。所有设置的更改都会实时反映在预览画布上,最后用户可以直接下载带有水印的图片。
页面结构
控制面板
控制面板位于页面左侧,包含所有水印参数的设置选项,包括文本输入、字体选择、滑块控件和位置按钮等。<div class="controls"> <div class="control-group"> <label for="watermarkText">水印文字</label> <textarea id="watermarkText" placeholder="请输入水印文字...">技术小丁</textarea> </div>
<div class="control-row"> <div class="control-group"> <label for="fontFamily">字体</label> <select id="fontFamily"> <option value="Arial">Arial</option> <option value="Helvetica">Helvetica</option> </select> </div> <div class="control-group"> <label for="fontSize">字号 (px)</label> <div class="range-input"> <input type="range" id="fontSize" min="12" max="120" value="24"> <span id="fontSizeValue">24</span> </div> </div> </div> </div>
预览区域
预览区域位于页面右侧,展示上传图片添加水印后的效果,同时提供上传按钮和下载按钮。<div class="preview"> <div class="button-group"> <button class="btn btn-primary" id="uploadBtn">选择图片</button> <button class="btn btn-success" id="downloadImage" disabled>下载图片</button> </div>
<div class="loading" id="loading"> <div class="spinner"></div> <p>正在处理图片...</p> </div>
<div id="uploadArea" class="upload-area"> <div class="upload-text">点击上传图片或拖拽到此处</div> <div class="upload-subtext">支持 JPG、PNG、GIF 格式</div> <input type="file" id="imageInput" accept="image/*" style="display: none;"> </div>
<div id="canvasContainer" class="canvas-container"> <canvas id="canvas"></canvas> </div></div>
核心功能实现
在图片上绘制水印
applyWatermark 函数先清除画布内容并绘制原始图片,然后根据用户的设置参数计算水印的位置和样式。Canvas 的 fillStyle 属性控制文字颜色,globalAlpha 属性控制透明度。function applyWatermark() { if (!originalImage) return; showLoading(true);
requestAnimationFrame(() => { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(originalImage, 0, 0, canvas.width, canvas.height);
const settings = getWatermarkSettings(); ctx.font = `${settings.fontSize}px ${settings.fontFamily}`; ctx.fillStyle = settings.textColor; ctx.globalAlpha = settings.opacity;
const metrics = ctx.measureText(settings.text); const textWidth = metrics.width; const textHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
if (settings.isTiled) { drawTiledWatermark(settings, textWidth, textHeight); } else { drawSingleWatermark(settings, textWidth, textHeight); }
ctx.globalAlpha = 1; showLoading(false); });}
水印位置计算
水印位置的选择采用了九宫格布局,用户可以在九个预设位置中选择一个。calculatePosition 函数负责根据选定位置计算水印的坐标,同时考虑了文本基线和边界的因素,确保文字在视觉上居中。function calculatePosition(settings, textWidth, textHeight) { let centerX = canvas.width / 2; let centerY = canvas.height / 2;
switch (settings.position) { case 'top-left': centerX = textWidth / 2; centerY = textHeight / 2; break; case 'top-center': centerY = textHeight / 2; break; case 'top-right': centerX = canvas.width - textWidth / 2; centerY = textHeight / 2; break; }
centerX += settings.offsetX; centerY += settings.offsetY;
return { centerX, centerY };}
平铺水印实现
drawTiledWatermark 函数实现了平铺水印功能,它通过计算旋转后文字的尺寸和间距,确定需要绘制多少行列的水印,从而使水印在整个画布上重复显示。function drawTiledWatermark(settings, textWidth, textHeight) { const sin = Math.abs(Math.sin(settings.rotation)); const cos = Math.abs(Math.cos(settings.rotation)); const rotatedWidth = textWidth * cos + textHeight * sin; const rotatedHeight = textWidth * sin + textHeight * cos;
const spacingX = rotatedWidth + 50; const spacingY = rotatedHeight + 50;
const cols = Math.ceil((canvas.width + spacingX) / spacingX); const rows = Math.ceil((canvas.height + spacingY) / spacingY);
for (let row = -1; row <= rows; row++) { for (let col = -1; col <= cols; col++) { const x = col * spacingX + settings.offsetX; const y = row * spacingY + settings.offsetY;
ctx.save(); ctx.textBaseline = 'middle'; ctx.textAlign = 'center'; ctx.translate(x + textWidth/2, y + textHeight/2); ctx.rotate(settings.rotation);
if (settings.hasStroke) drawStroke(settings.text); ctx.fillText(settings.text, 0, 0); ctx.restore(); } }}
描边效果
描边效果增强了水印文字的可读性,特别是在复杂背景上。drawStroke 函数使用 strokeText 方法为文字添加黑色描边。function drawStroke(text) { ctx.strokeStyle = 'rgba(0, 0, 0, 0.8)'; ctx.lineWidth = Math.max(2, ctx.measureText(text).width / 15); ctx.lineJoin = 'round'; ctx.miterLimit = 2; ctx.strokeText(text, 0, 0);}
扩展建议
支持图片格式转换和压缩选项
实现图形水印功能
增加水印模板保存与重用机制
添加批量处理多张图片的能力
源码地址
git地址:https://gitee.com/ironpro/hjdemo/blob/master/image-watermark/index.html
阅读原文:原文链接
该文章在 2026/1/20 10:28:09 编辑过