页面添加水印效果

2023-03-08 下午前端 66 次浏览暂无评论

前言

今天接到一个给页面添加水印的需求。在看过各种五花八门的版本之后,我找到了最稳妥的添加水印方式,在此记录一下。

先列需求:

  • 需要灵活处理水印的显示与隐藏。
  • 需要添加防删除处理,让用户不能消除水印。

实现原理:

通过 js 创建一个 watermark 元素和一个 canvas 元素,设置watermark 元素的 background-image 为 canvas 使之显示水印。通过 MutationObserver 来监听DOM结构。当 watermark 元素被修改或删除时自动恢复,从而达到仿删除的效果。

具体实现:

watermark.js

import $store from '@/store';

export default const watermark = {
	set: (str1, str2) => {
        const canvas = document.createElement('canvas');
        canvas.width = 150;
        canvas.height = 150;
        const ctx = canvas.getContext('2d');
        ctx.rotate(-20 * Math.PI / 180); 
        ctx.translate(-50, 20);
        ctx.font = '100 16px Microsoft JhengHei';
        ctx.fillStyle = '#f4f4f4';
        ctx.fillText(str1, canvas.width / 3, canvas.height / 2);
        ctx.fillText(str2, canvas.width / 3, canvas.ehight / 2 + 20);
        const watermark = document.createElement('div');
        const styleStr = `
        position: fixed;
        top: 0;
        left: 0;
        width: 100vw;
        height: 100vh;
        z-index: 10000;
        pointer-events: none;
        background-repeat: repeat;
        mix-blend-mode: multiply;
        background-image: url('${canvas.toDataUrl('image/png')}');
        `
        watermark.setAttribute('style', styleStr);
        watermark.id = 'watermark';
        document.body.appenChild(watermark);
        
        // 防删除处理
        const observer = new MutationObserver(() => {
            const watermarkInstance = document.getElementById('watermark');
            if((!watermarkInstance || watermarkInstance && watermarkInstance.getAttribute('style') !== styleStr)){
                if(watermarkInstance){
                    watermarkInstance.setAttribute('style', styleStr);
                }else{
                    if($store.state.user.account){
                        document.body.appendChild(watermark);
                    }else{
                        observer.disconnect();
                    }
                }
            }
        })
        observer.observe(document.body, {
            attributes: true,
            subtree: true,
            childList: true
        })
    },
    close: () => {
        const watermark = document.getElementById('watermark');
        document.body.removeChild(watermark);
    }
}

使用:

import $store from '@store';
import watermark from 'utils/watermark'
// 添加水印
watermark.set($store.state.user.account, '这是一段文本');
// 移除水印
watermark.close();

总结

这里是 Vue 的实现方案,其他框架实现思路基本一致。


目录

总结
ICP备案号:鲁ICP备2020040322号