深色模式
网页背景水印
原理是在canvas或svg创建背景图片,输出 base64
格式图片附在页面元素上面,调整图片颜色,同时通过 cs s样式 points-events:none
隐藏点击效果。
canvas水印
预览链接 网页预览打开
预览效果如下, 可以看到已经有了背景水印
详细代码
html
<body>
<div>页面内容</div>
<script>
function canvasWM({
container = document.body,
width = 200,
height = 100,
text = '请勿泄露',
zIndex = 1000,
rotate = -14,
fillStyle = 'rgba(184, 184, 184, 0.4)',
}) {
// 创建画布
const canvas = document.createElement('canvas');
// 设置画布样式
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
// canvas.setAttribute('display', 'none');
const ctx = canvas.getContext('2d');
// 设置内容样式
ctx.font = '20px Microsoft YaHei';
// 文本横向对齐方式
ctx.textAlign = 'left';
// 文本纵向对齐方式
ctx.textBaseline = 'middle';
ctx.fillStyle = fillStyle;
ctx.rotate((Math.PI / 180) * rotate);
// 设置文本内容
ctx.fillText(text, canvas.width / 3, canvas.height / 2);
// 获取页面水印元素,替换样式
const base64URL = canvas.toDataURL();
let wm = document.querySelector('.wm');
const wmDiv = wm || document.createElement('div');
const wmStyle = `
position: fixed;
top: 0;
left: 0;
right: 0;
right: 0;
width: 100%;
height: 100%;
z-index: ${zIndex},
pointer-events:none;
background-image: url('${base64URL}');
background-repeat: repeat;
`;
wmDiv.setAttribute('style', wmStyle);
wmDiv.classList.add('wm');
if (!wm) {
container.insertBefore(wmDiv, container.firstChild);
}
}
canvasWM({});
</script>
<style>
body {
height: 100vh;
}
</style>
</body>
优缺点
优点: 实现简单
缺点:使用了页面css和div元素,可以被屏蔽掉,也可以直接删除元素,从而删除水印。
svg水印
与canvas类似,不过是水印换成了svg图片了, 好处是兼容性更好
js
const svgStr = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${width}">
<text x="50%" y="50%" dy="12px"
text-anchor="middle"
stroke="#000000"
stroke-width="1"
stroke-opacity="${opacity}"
fill="none"
transform="rotate(-45, 120 120)"
style="font-size: ${font};">
${content}
</text>
</svg>`;
const base64Url = `data:image/svg+xml;base64,${window.btoa(unescape(encodeURIComponent(svgStr)))}`;
无论是canvas还是svg都是在页面插入元素,是可以被屏蔽或者删除掉的。如果元素被删除掉了,就不能防止别人截图了。
可以考虑设置定时器,定期刷新页面。网上有另外的方案,使用 MutationObserver
监听 dom 的变动,比如 wm样式改变或者被删除都会重新渲染, 这种方案更好。但是着这种方案中 container
元素发生变化可以监听, 但是当删除 container
后,监听也就停止了。
详细代码
html
<body>
<div>页面内容</div>
<script>
function canvasWM({
container = document.body,
width = 200,
height = 100,
text = '请勿泄露',
zIndex = 1000,
rotate = -14,
fillStyle = 'rgba(184, 184, 184, 0.4)',
}) {
console.log(`渲染水印`);
const args = arguments[0];
// 创建画布
const canvas = document.createElement('canvas');
// 设置画布样式
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
// canvas.setAttribute('display', 'none');
const ctx = canvas.getContext('2d');
// 设置内容样式
ctx.font = '20px Microsoft YaHei';
// 文本横向对齐方式
ctx.textAlign = 'left';
// 文本纵向对齐方式
ctx.textBaseline = 'middle';
ctx.fillStyle = fillStyle;
ctx.rotate((Math.PI / 180) * rotate);
// 设置文本内容
ctx.fillText(text, canvas.width / 3, canvas.height / 2);
// 获取页面水印元素,替换样式
const base64URL = canvas.toDataURL();
let wm = document.querySelector('.wm');
const wmDiv = wm || document.createElement('div');
const wmStyle = `
position: fixed;
top: 0;
left: 0;
right: 0;
right: 0;
width: 100%;
height: 100%;
z-index: ${zIndex},
pointer-events:none;
background-image: url('${base64URL}');
background-repeat: repeat;
`;
wmDiv.setAttribute('style', wmStyle);
wmDiv.classList.add('wm');
if (!wm) {
container.insertBefore(wmDiv, container.firstChild);
}
const MutationObserver = window.MutationObserver;
if (MutationObserver) {
// 观察器的配置(需要观察什么变动)
const config = { attributes: true, childList: true, subtree: true };
// 当观察到变动时执行的回调函数
const callback = function (mutationsList, observer) {
// Use traditional 'for loops' for IE 11
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
console.log('A child node has been added or removed.');
} else if (mutation.type === 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.');
}
}
// 之后,可停止观察, 避免重复调用
observer.disconnect();
canvasWM(JSON.parse(JSON.stringify(args)));
};
// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(callback);
// 以上述配置开始观察目标节点
observer.observe(container, config);
}
}
canvasWM({});
</script>
<style>
body {
height: 100vh;
}
</style>
</body