我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情
最近公司内部系统需要添加动态水印-水印内容为当前时间戳+用户名。特别希望大家能提供其他思路。
1. 动态水印需满足什么条件
- 水印可以实时变化
- 铺满整个页面
- 不能被用户通过控制台删除Elements将水印删除
2. 如何满足上面的条件
- 使用定时器setInterval
- 使用
backgroundImage和background-repeat: repeat; - 使用
MutationObserver监听DOM变化
3. 代码实现
下面的代码可以自己封装成hooks。
// 监听DOM变化,防止直接删除DOM导致水印消失
useEffect(() => {
const targetNode = document.body;
const config = { childList: true, };
const callback = (mutationsList) => {
for(let i = 0; i < mutationsList.length; i++) {
const { removedNodes } = mutationsList[i];
for(let j = 0; j < removedNodes.length; j++) {
if (removedNodes[j].className === "watermask") {// 限制某些页面应用水印
if ((props.location.pathname.includes("xxx/detail/") || props.location.pathname.includes("xxx/"))) {
document.body.appendChild(watermask);
}
}
}
}
};
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
return () => {
observer.disconnect();
};
}, [props.location.pathname]);
// 添加明水印
useEffect(() => {
if (!userInfo.userName) return;// 用户信息通过各自系统内API获取
if (!(props.location.pathname.includes("xxx/detail/") || props.location.pathname.includes("xxx/"))) {
if (document.body.contains(watermask)) {
document.body.removeChild(watermask);
}
return;
} else if (!document.body.contains(watermask)) {
document.body.appendChild(watermask);
}
// 通过canvas方案生成水印
const createWaterMask = () => {
const angle = -20;
const txt1 = userInfo.userName;
const txt2 = getFormatteredDate(getParsedDate(new Date()), "yyyy-MM-dd hh:mm:ss");
const canvas = document.createElement("canvas");
canvas.width = 340;
canvas.height = 214;
const ctx = canvas.getContext("2d");
ctx.clearRect(0,0,340,214);
ctx.fillStyle = "#7E84A3";
ctx.font = `18px Microsoft Yahei`;
ctx.globalAlpha = 0.08;
ctx.rotate(Math.PI / 180 * angle);
ctx.fillText(txt1, 0, 100);
ctx.fillText(txt2, 0, 130);
return canvas.toDataURL();
};
const timer = setInterval(() => {
watermask.style.backgroundImage = `url(${createWaterMask()})`;
}, 1000);
return () => {
clearInterval(timer);
}; }, [userInfo, props.location.pathname]);