如何在react项目中添加动态水印

377 阅读1分钟

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

最近公司内部系统需要添加动态水印-水印内容为当前时间戳+用户名。特别希望大家能提供其他思路。

1. 动态水印需满足什么条件

  1. 水印可以实时变化
  2. 铺满整个页面
  3. 不能被用户通过控制台删除Elements将水印删除

2. 如何满足上面的条件

  1. 使用定时器setInterval
  2. 使用backgroundImagebackground-repeat: repeat;
  3. 使用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]);