> 文章列表 > vue3前端页面添加水印

vue3前端页面添加水印

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>

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


  • 以上内容仅供参考学习!如有错误,麻烦指正!如有雷同,纯属巧合!