开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
给页面添加水印,你有什么招数
最近一位同学找到我,问:‘如何给页面添加水印,而且用户不能去除水印’,乍一看这题目,看似简单但要做完美还需要有一定前端知识储备的。为了保护知识产权,或者后台系统快速定位到个人,页面水印的存在是非常有必要的。接下来会尝试实现这个需求,本文从以下重点展开:
- 如何生成水印
- 将水印放到页面上
- 如何禁止用户删除、篡改水印
- 如何把水印做得更隐蔽
如何生成水印
如果水印是用来溯源,那么水印的内容可能会包含用户信息,因此水印的内容不是固定的。对于这种场景,一般可以由前端完成,通过 canvas 进行绘制,或者通过 svg 绘制也可以,这样可以减少与服务端的请求和资源开销。下面分别实现一下
// canvas 生成方式
const canvas = document.createElement("canvas");
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
const ctx = canvas.getContext("2d");
const img = new Image();
img.onload = () => {
ctx.drawImage(img, 0, 0);
canvas.toBlob((blob) => {
const blobURL = URL.createObjectURL(blob);
window.open(blobURL);
URL.revokeObjectURL(blobURL);
});
};
img.src = `data:image/svg+xml;charset=utf-8,${svg}`;
// svg 生成方式
<svg width="400" height="400" style="border: 1px solid red">
<text style="fill: pink;fill-opacity:'0.2';transform: rotateX(45deg);">我是水印</text>
</svg>
除了前端生成图片,也可以通过服务端返回图片的方式生成水印图片。
将水印放到页面上
在页面中插入一个全屏的,固定在页面的 div ,设置这个 div 的 background-image ,并设置 z-index 为最顶层,这样水印就出现在页面上了,但是这个 div 可能会遮挡其他元素,影响页面操作,因此还需要给这个元素增加 pointer-events: none; 属性,防止影响用户其他操作。
<div id="watermark"></div>
<style>
#watermark{
z-index: 9999;
pointer-events: none;
}
</style>
如何禁止用户删除、篡改水印
要防止一些人为修改,比如在浏览器控制台直接修改或删除对应的 DOM 元素,可以通过 MutationObserver 实现,监听用户行为,水印被修改或删除马上插入新的水印。
MutationObserver
MutationObserver 接口提供了监视对 DOM 树所做更改的能力。它被设计为旧的 Mutation Events 功能的替代品,该功能是 DOM3 Events 规范的一部分。MutationObserver 创建并返回一个新的 MutationObserver 它会在指定的 DOM 发生变化时被调用。
// 选择需要观察变动的节点
const targetNode = document.getElementById("some-id");
// 观察器的配置(需要观察什么变动)
const config = { attributes: true, childList: true, subtree: true };
// 当观察到变动时执行的回调函数
const callback = function (mutationsList, observer) {
const watermark = document.getElementById("watermark");
watermark.innerHTML = `
<svg width="400" height="400" style="border: 1px solid red">
<text style="fill: pink;fill-opacity:'0.2';transform: rotateX(45deg);">我是水印</text>
</svg>
`;
};
// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(callback);
// 以上述配置开始观察目标节点
observer.observe(targetNode, config);
// 之后,可停止观察
observer.disconnect();
如何把水印做得更隐蔽
可以使用暗水印技术,将水印添加到图片或其他地方,可参考一下这篇文章: 链接