网页上的原创图片经常被人一键另存、批量采集,辛苦制作的内容转眼就成了别人的素材。给图片嵌入水印是最常用也是最有效的保护手段之一。html5提供了强大的canvas绘图能力,配合一些CSS技巧,我们完全可以在前端实现文字水印、图片水印甚至半透明平铺水印层。下面就详细介绍几种在html5中嵌入水印图片的具体做法,以及如何组合这些手段达到防盗取的效果。

方式一:用canvas把水印直接绘制进图片
canvas是html5最核心的绘图接口,它的思路是先把原图加载到画布上,再用fillText或者drawImage把水印文字、水印logo画上去,最后导出合成后的图片。这种方式生成的是一张真正带水印的新图片,即使别人下载了,水印也牢牢地烧在像素里,无法通过删除DOM节点来去除。
基本流程是:创建一个canvas元素,设置宽高与原图一致,等待图片加载完成(注意跨域问题,本地测试建议把图片放到同一域名下,或让图片服务器返回Access-Control-Allow-Origin头并设置img.crossOrigin = 'anonymous'),然后依次绘制原图和水印,最后通过toDataURL导出。
<canvas id="myCanvas" width="800" height="500"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.crossOrigin = 'anonymous'; // 解决跨域画布污染问题
img.src = 'https://ipipp.com/images/photo.jpg';
img.onload = function () {
// 先绘制原图
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// 设置水印文字样式
ctx.font = '24px Microsoft YaHei';
ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
ctx.textAlign = 'right';
// 在右下角绘制水印
ctx.fillText('ipipp.com 版权所有', canvas.width - 20, canvas.height - 20);
// 导出合成后的图片
const result = canvas.toDataURL('image/png');
console.log(result);
};
</script>如果想让水印更明显,可以给文字加上阴影效果,使用ctx.shadowColor设置阴影颜色,再用ctx.shadowBlur设置模糊半径,这样即使图片背景是白色,水印也能看清。另外还可以用ctx.rotate让水印旋转一定角度,视觉上更像专业的版权保护标记。
方式二:制作半透明水印覆盖层防盗
除了把水印烧进图片,还有一种更灵活的做法:在页面上叠加一个透明的水印层。这个水印层铺满整个展示区域,用户看到的是图片加水印的组合效果,右键保存时保存到的只是底层干净图片或干脆无法保存。虽然这种方式的防护强度不如canvas合成,但胜在不修改原图、实现简单,特别适合展示类的页面。
具体实现上,可以先在服务器或前端生成一张小的水印图片,然后通过CSS的background-repeat: repeat平铺到覆盖层上。也可以纯前端用canvas生成水印背景,再设置为元素的背景图,这样连水印图片文件都不需要准备。
<div class="img-wrapper">
<img src="photo.jpg" alt="受保护的图片">
<div class="watermark-layer"></div>
</div>
<script>
// 用canvas动态生成一张水印平铺图
function makeWatermark(text) {
const c = document.createElement('canvas');
c.width = 200;
c.height = 150;
const cx = c.getContext('2d');
cx.rotate(-20 * Math.PI / 180); // 倾斜20度
cx.font = '16px sans-serif';
cx.fillStyle = 'rgba(0, 0, 0, 0.08)';
cx.fillText(text, 20, 100);
return c.toDataURL();
}
document.querySelector('.watermark-layer').style.backgroundImage =
'url(' + makeWatermark('ipipp.com 专属水印') + ')';
</script>对应的CSS部分需要把覆盖层绝对定位到图片上方,并设置pointer-events: none,这样水印层不会阻挡图片的正常交互,同时视觉上完全覆盖在图片之上。
.img-wrapper {
position: relative;
display: inline-block;
}
.watermark-layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-repeat: repeat;
pointer-events: none; /* 不拦截鼠标事件 */
}进阶一点,还可以监听窗口的resize事件重新生成水印,或者在用户切换页面、打开控制台时动态加深水印透明度,提高破解成本。有些网站会把用户ID、登录名等信息嵌入水印,一旦图片外流就能追溯到具体的人,这就是所谓的盲水印溯源思路的简化版。
方式三:前端防护与后端配合的综合防盗方案
需要明确一点:任何纯前端的防护都无法百分百防止截图和录屏,前端方案的作用是提高盗图的门槛。所以真正稳妥的防盗取方案一定是前后端配合的。服务端可以在图片输出时动态叠加水印,比如用PHP的GD库、Node.js的sharp库,在图片请求阶段就完成水印合成,用户拿到的每一张图都自带水印,前端再怎么折腾也绕不开。
服务端方案之外,还有几个前端配套措施值得做:第一,禁用右键菜单,虽然对专业用户没用,但能挡住大部分普通用户;第二,把图片放到CSS的background-image中展示,而不是用img标签,这样右键另存为会失效;第三,对图片URL做时效签名,链接过期后直接失效,防止被批量采集。
// 禁用右键和拖拽
document.addEventListener('contextmenu', function (e) {
e.preventDefault();
});
document.addEventListener('dragstart', function (e) {
if (e.target.tagName === 'IMG') e.preventDefault();
});对于要求更高的场景,比如付费图库、设计素材站,可以研究数字盲水印技术:把版权信息编码后嵌入图片频域数据中,肉眼完全看不出变化,但通过解密算法可以提取出版权信息。这方面已有成熟的开源库如blind-watermark可用,即使图片被裁剪、压缩、加滤镜,依然有较大概率还原出隐藏的水印内容。
总结一下,html5嵌入水印图片主要有两条路线:canvas合成式水印防护强度高、不可分割,适合最终交付的图片;覆盖层式水印实现简单、不破坏原图,适合网页展示场景。再配合服务端动态水印、URL签名和禁用右键等手段,就能搭建出一套比较完整的图片防盗体系。根据自己的业务场景选择合适的组合,才能在保护版权和用户体验之间找到平衡点。