前段时间做某系统审核后台,出现了审核人员截图把内容外泄露的情况,虽然截图内容不是特别敏感,但是安全问题还是不能忽视。于是便在系统页面上面加上了水印,对于审核人员截图等敏感操作有一定的提示作用。
网页水印生成解决方案
通过canvas生成水印
Canvas兼容性
这里我们用canvas来生成base64图片,通过CanIUse网站查询兼容性,如果在移动端以及一些管理系统使用,兼容性问题可以完全忽略。
HTMLCanvasElement.toDataURL 方法返回一个包含图片展示的 data URI 。可以使用 type 参数其类型,默认为 PNG 格式。图片的分辨率为96dpi。
如果画布的高度或宽度是0,那么会返回字符串“data:,”。
如果传入的类型非“image/png”,但是返回的值以“data:image/png”开头,那么该传入的类型是不支持的。
Chrome支持“image/webp”类型。具体参考HTMLCanvasElement.toDataURL
具体代码实现如下:
(function () {
function __canvasWM({
container = document.body,
width ='130px',
height ='130px',
textAlign ='center',
textBaseline ='middle',
font ="18px Microsoft Yahei",
fillStyle ='rgba(128, 128, 128, 0.8)',
content ='',
rotate ='30',
zIndex =1000
} = {}) {
const args = arguments[0];
const canvas = document.createElement('canvas');
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
const ctx = canvas.getContext("2d");
ctx.textAlign = textAlign;
ctx.textBaseline = textBaseline;
ctx.font = font;
ctx.fillStyle = fillStyle;
ctx.rotate(Math.PI /180 * rotate);
ctx.fillText(content, parseFloat(width) /2, parseFloat(height) /2);
const base64Url = canvas.toDataURL();
const __wm = document.querySelector('.__wm');
const watermarkDiv = __wm || document.createElement("div");
const styleStr =`
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
z-index:${zIndex};
pointer-events:none;
background-repeat:repeat;
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');
// 只在__wm元素变动才重新调用 __canvasWM
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) {//CMD
module.exports = __canvasWM;
}else if (typeof define =='function' && define.amd) {// AMD
define(function () {
return __canvasWM;
});
}else {
window.__canvasWM = __canvasWM;
}
})();
// 调用
__canvasWM({
content: “水印内容”
});