前言
页面水印是一种数字保护,版权保护,知识产权保护的手段,为防止他人盗用,可以快速定位到个人
目标
- 提高安全性,不可以通过控制台修改隐藏水印
- 前端水印不影响页面的正常使用
- 前端水印的显示方式是页面整体旋转某个角度
技术分析
- 前端网页要整体显示水印,首先生成一个水印
- 然后将水印作为背景图(重复显示这一个水印repeat)填充整个页面
- 然后检测水印变化,如果变化重新生成。不会被隐藏。
实现方案
首先生成一个水印
function canvasWM({
container = document.body,
width = '200px',
height = '200px',
textAlign = 'center',
textBaseLine = 'middle',
font = '12px SourceHanSansSCVF-Regular',
fillStyle = 'rgba(0,0,0,0.1)',
content = '前端水印',
zIndex = 10
} = {}) {
var args = arguments[0];
var canvas = document.createElement('canvas');
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
var ctx = canvas.getContext('2d');
ctx.textAlign = textAlign;
ctx.textBaseline = textBaseline;
ctx.font = font;
ctx.fillStyle = fillStyle;
ctx.fillText(content, parseFloat(width) / 2, parseFloat(height) / 2);
var base64Url = canvas.toDataURL();
}
链接: canvas如何生成dataUrl
以上代码生成的图片
function svgWM({
container = document.body,
width = '200px',
height = '200px',
fontSize = '12px',
fontFamily = 'SourceHanSansSCVF-Regular',
fill= 'rgb(0,0,0,0.06)',
content = '前端水印',
zIndex = 10
} = {}) {
const args = arguments[0];
const svgStr = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
<text x="50%" y="50%"
text-anchor="middle"
font-family=${fontFamily}
fill=${fill}
style="font-size: ${fontSize};">
${content}
</text>
</svg>`;
const base64Url = `data:image/svg+xml;base64,${window.btoa(unescape(encodeURIComponent(svgStr)))}`;
}
将水印作为背景图
以上代码实现了一个水印的图片,然后创建一个div元素,把水印作为背景图
const __wm = document.querySelector('.__wm');
const watermarkDiv = __wm || document.createElement("div");
const styleStr = `
position:fixed;
top:0px;
left:0px;
width:100%;
height:1400%;
z-index:${zIndex};
pointer-events:none; // 元素永远不会成为鼠标事件的target
background-repeat:repeat; // 重复水印显示
transform: rotate(-24deg) translateZ(0); // 页面整体旋转角度
overflow:hidden;
background-image:url('${base64Url}')`;
watermarkDiv.setAttribute('style', styleStr);
watermarkDiv.classList.add('__wm');
以上代码中的旋转会导致图片上的水印字体模糊,暂时未解决
检测水印变化,做出调整
MutationObserver接口提供了监视对DOM树所做更改的能力 Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。 使用MutationObserver构造函数,新建一个观察器实例,实例的有一个回调函数,该回调函数接受两个参数,第一个是变动数组,第二个是观察器实例。MutationObserver 的实例的observe方法用来启动监听,它接受两个参数 MutationObserver只能监测到诸如属性改变、增删子结点等,对于自己本身被删除,是没有办法的可以通过监测父结点来达到要求
if (!__wm) {
container.style.position = 'relative';
container.insertBefore(watermarkDiv, container.firstChild);
}
const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
if (MutationObserver) {
let mo = new MutationObserver(function () {
const __wm = document.querySelector('.__wm');
if ((__wm && __wm.getAttribute('style') !== styleStr) || !__wm) {
mo.disconnect();
mo = null;
__canvasWM(JSON.parse(JSON.stringify(args)));
}
});
mo.observe(container, {
attributes: true,
subtree: true,
childList: true
})
}
调用
canvasWM({
content: '显示水印'
});
整体代码
(function () {
function svgWM({
container = document.body,
width = '200px',
height = '200px',
fontSize = '12px',
fontFamily = 'SourceHanSansSCVF-Regular',
fill= 'rgb(0,0,0,0.06)',
content = '前端水印',
zIndex = 10
} = {}) {
const args = arguments[0];
const svgStr = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
<text x="50%" y="50%"
text-anchor="middle"
font-family=${fontFamily}
fill=${fill}
style="font-size: ${fontSize};">
${content}
</text>
</svg>`;
const base64Url = `data:image/svg+xml;base64,${window.btoa(unescape(encodeURIComponent(svgStr)))}`;
const __wm = document.querySelector('.__wm');
const watermarkDiv = __wm || document.createElement("div");
const styleStr = `
position:fixed;
top:0px;
left:0px;
width:100%;
height:1400%;
z-index:${zIndex};
pointer-events:none; // 元素永远不会成为鼠标事件的target
background-repeat:repeat; // 重复水印显示
transform: rotate(-24deg) translateZ(0); // 页面整体旋转角度
overflow:hidden;
background-image:url('${base64Url}')`;
watermarkDiv.setAttribute('style', styleStr);
watermarkDiv.classList.add('__wm');
if (!__wm) {
container.style.position = 'relative';
container.insertBefore(watermarkDiv, container.firstChild);
}
const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
if (MutationObserver) {
let mo = new MutationObserver(function () {
const __wm = document.querySelector('.__wm');
if ((__wm && __wm.getAttribute('style') !== styleStr) || !__wm) {
mo.disconnect();
mo = null;
__canvasWM(JSON.parse(JSON.stringify(args)));
}
});
mo.observe(container, {
attributes: true,
subtree: true,
childList: true
})
}
}
if (typeof module != 'undefined' && module.exports) {
module.exports = __canvasWM;
} else if (typeof define == 'function' && define.amd) {
define(function () {
return __canvasWM;
});
} else {
window.__canvasWM = __canvasWM;
}
})();
|