vue3前端页面添加水印

在页面中,往往会添加水印来展示一些信息。例如在一些页面中加上自己特有的信息。使得别人在截图转发时也能看到这些信息。又好比一家公司的内部系统,可以在页面添加访问者的水印,使得用户在截图转发敏感信息之后,通过截图中的水印可以追寻到泄露信息之人。

在最开始实现水印的时候,我的想法是在一个层级比较高的div中添加相关信息,然后循环铺满整个页面。这样 就可以实现页面的水印功能。但是又存在一个新的问题,如果我在页面的代码中将水印中我自己的个人信息改成别人的信息,然后截图传播出去,到时候是不是就追寻不到截图的人了呢?

鉴于这样的情况,我想到了两个方法:①是将水印转换为svg,②是使用canvas绘制水印。

最后我选择了vanvas

于是:便有了如下的代码

function createWaterMark() {
    const angle = -30; //旋转角度
    const txt = props.text; //水印文字
    const canvas = document.createElement('canvas'); //创建画布
    canvas.width = 280; //画布宽
    canvas.height = 200; //画布高
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, 280, 200); //清除画布内容
    ctx.fillStyle = '#000'; //填充颜色
    ctx.globalAlpha = 0.2; //透明度
    ctx.font = `16px YaHei`; //字体属性
    ctx.rotate((Math.PI / 180) * angle); //旋转
    ctx.fillText(txt, 10, 100); //填充字体
    if (props.time) {
        //填充时间
        ctx.fillText(watermark_time, 0, 120);
    }
    if (props.date && !props.time) {
        //填充日期
        ctx.fillText(watermark_date, 0, 120);
    }
    return canvas.toDataURL();
}

在这里我是将水印封装成一个组件,希望能用在不同的系统中,因此水印的内容选择了传值的方式。第一行是用户信息,第二行可以选择带时间的日期和不带时间的日期。

就在这样新增水印之后我正在窃窃自喜的时候我又发现了一个新的问题:如果我在页面的Dom中把该Dom的节点删除了呢?这个时候整个水印就消失不见了。没有水印的页面是在是不安全。

于是,就开始百度…

然后看到一个似乎可以实现的方式:监测Dom,如果该Dom节点被删除了,直接重新刷新页面。

于是,整个水印的操作代码就变成了下面这样:

<template>
    <div></div>
</template>

<script setup>
import moment from 'moment';
import { onMounted, getCurrentInstance } from 'vue';
defineOptions({
    name: 'Watermark',
    inheritAttrs: false
});

const props = defineProps({
    text: String,
    time: Boolean,
    date: Boolean
});
let watermark_date = moment(new Date()).format('YYYY-MM-DD');
let watermark_time = moment(new Date()).format('YYYY-MM-DD HH:mm:ss');

const cb = function (mutationList, observer) {
    for (const mutation of mutationList) {
        if (mutation.type === 'childList') {
            const { removedNodes = [] } = mutation;
            // 如果监听到水印容器变化,那么就重载页面
            const node = Array.prototype.find.apply(removedNodes, [
                (node) => node.className === 'watermark'
            ]);
            //如果水印被删除,重新加载页面
            if (node) {
                window.location.reload();
            }
        }
    }
};

function createWaterMark() {
    const angle = -30; //旋转角度
    const txt = props.text; //水印文字
    const canvas = document.createElement('canvas'); //创建画布
    canvas.width = 280; //画布宽
    canvas.height = 200; //画布高
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, 280, 200); //清除画布内容
    ctx.fillStyle = '#000'; //填充颜色
    ctx.globalAlpha = 0.2; //透明度
    ctx.font = `16px YaHei`; //字体属性
    ctx.rotate((Math.PI / 180) * angle); //旋转
    ctx.fillText(txt, 10, 100); //填充字体
    if (props.time) {
        //填充时间
        ctx.fillText(watermark_time, 0, 120);
    }
    if (props.date && !props.time) {
        //填充日期
        ctx.fillText(watermark_date, 0, 120);
    }
    return canvas.toDataURL();
}
const watermarkDiv = document.createElement('div');
watermarkDiv.className = 'watermark';
watermarkDiv.style.backgroundImage = `url(${createWaterMark()})`;

onMounted(() => {
    const app = document.querySelector('#app');
    //监听Dom改变
    const observer = new MutationObserver(cb);
    observer.observe(app, {
        attributes: true,
        childList: true
    });
    app.appendChild(watermarkDiv);
});
</script>

<style>
.watermark {
    position: fixed;
    width: 100%;
    height: 100%;
    padding: 40px 0 0 0;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    pointer-events: none;
    z-index: 9999999;
    display: flex;
    flex-wrap: wrap;
    overflow: hidden;
}
</style>

在写之前,没想到一个小小的水印还有这么多需要注意的地方。


  • 以上内容仅供参考学习!如有错误,麻烦指正!如有雷同,纯属巧合!
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值