uni-app项目中添加全局水印(不修改App.vue)
·
1.首先创建watermark.js(我的项目中是放在utils文件夹中,如果是其他文件下,记得更改引入路径),代码如下:
/**
* 全局水印工具类(支持用户信息动态更新)
*/
import {parseTime} from '@/utils/common.js';
export default class Watermark {
constructor(options = {}) {
// 默认配置
this.defaults = {
fontSize: 12,
color: 'rgba(150, 150, 150, 0.15)',
rotate: -15, // 旋转角度
rowSpace: 100, // 行间距
colSpace: 160, // 列间距
zIndex: 9998, // 水印层级
userInfo: {} // 用户信息({ name: '', id: '' })
};
this.options = { ...this.defaults, ...options };
this.watermarkId = 'uni-global-watermark'; // 水印元素ID
this.observer = null; // 防篡改观察者
}
// 初始化水印
init() {
// 先移除已存在的水印(避免重复创建)
this.remove();
// 创建水印元素
const watermarkEl = document.createElement('div');
watermarkEl.id = this.watermarkId;
watermarkEl.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
pointer-events: none;
z-index: ${this.options.zIndex};
background-repeat: repeat;
`;
// 生成水印背景图
this.updateWatermarkUrl(watermarkEl);
// 添加到页面
document.body.appendChild(watermarkEl);
// 启动防篡改监听
this.watchTamper(watermarkEl);
}
// 更新水印图片(支持动态修改用户信息)
update(options) {
this.options = { ...this.options, ...options };
const watermarkEl = document.getElementById(this.watermarkId);
if (watermarkEl) {
this.updateWatermarkUrl(watermarkEl);
}
}
// 生成水印背景图URL
updateWatermarkUrl(watermarkEl) {
const { userInfo, fontSize, color, rotate, rowSpace, colSpace } = this.options;
// 格式化用户信息为多行文本
const textLines = [];
if (userInfo.nickName) textLines.push(`${userInfo.nickName}|${parseTime(new Date())}`);
const text = textLines.length > 0 ? textLines.join('\n') : '未登录用户';
// 创建Canvas绘制水印
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = colSpace;
canvas.height = rowSpace;
// 设置字体样式
ctx.font = `${fontSize}px sans-serif`;
ctx.fillStyle = color;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
// 旋转画布
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate((rotate * Math.PI) / 180);
ctx.translate(-canvas.width / 2, -canvas.height / 2);
// 绘制多行文本
text.split('\n').forEach((line, index) => {
const y = canvas.height / 2 + (index - (text.split('\n').length - 1) / 2) * fontSize;
ctx.fillText(line, canvas.width / 2, y);
});
// 设置为背景图
watermarkEl.style.backgroundImage = `url(${canvas.toDataURL('image/png')})`;
}
// 监听水印是否被篡改(删除/隐藏)
watchTamper(watermarkEl) {
// 停止之前的监听
if (this.observer) this.observer.disconnect();
// 创建观察者
this.observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
// 检查水印是否被移除
if (!document.getElementById(this.watermarkId)) {
this.init(); // 重新创建
} else {
// 检查水印是否被隐藏
const style = getComputedStyle(watermarkEl);
if (style.display === 'none' || style.opacity === '0' || style.zIndex < this.options.zIndex) {
watermarkEl.style.display = 'block';
watermarkEl.style.opacity = '1';
watermarkEl.style.zIndex = this.options.zIndex;
}
}
});
});
// 监听水印元素和父节点变化
this.observer.observe(watermarkEl, { attributes: true, attributeFilter: ['style', 'id'] });
this.observer.observe(document.body, { childList: true, subtree: true });
}
// 移除水印
remove() {
const watermarkEl = document.getElementById(this.watermarkId);
if (watermarkEl) {
document.body.removeChild(watermarkEl);
}
if (this.observer) {
this.observer.disconnect();
}
}
}
2.在main.js中引入watermark.js
import Watermark from '@/utils/watermark';
// 初始化水印实例
const watermark = new Watermark({
fontSize: 12,
color: 'rgba(100, 100, 100, 0.12)',
zIndex: 9998
});
// 从Vuex获取初始用户信息并创建水印
function initWatermarkWithUser() {
const userInfo = JSON.parse(store.state.user.userInfo) || {};
watermark.update({ userInfo });
}
// 首次初始化水印
if (process.env.VUE_APP_PLATFORM === 'h5') { // 仅H5端生效
// 等待DOM加载完成
document.addEventListener('DOMContentLoaded', () => {
watermark.init();
initWatermarkWithUser();
});
}
// 监听用户信息变化(登录/退出时自动更新水印)
store.watch(
// 根据自身项目获取存储的用户信息
(state) => store.state.user.userInfo,
(newUserInfo) => {
watermark.update({ userInfo: JSON.parse(newUserInfo) });
},
{ deep: true }
);
更多推荐



所有评论(0)