使用工具
(1)、Vue3+Vite+TS
组件功能:
(1)水印将悬浮于对应区域的顶部,但并不会影响页面其他dom元素的相关操作。
(2)水印无法通过F12调试工具进行删除或样式修改。
(3)水印可自定义文字,字体大小,文字间隔。
1、watermark.ts
export function addWatermark(canvas: HTMLCanvasElement, watermarkText: string) {
if (!canvas) return;
// 获取父容器的尺寸
const parentRect = canvas.parentElement?.getBoundingClientRect();
if (!parentRect) return;
// 使用视口宽度和高度设置canvas的尺寸(css的宽高设置加上canvas的宽高属性设置,可以保证当父组件宽高变化时,canvas不会超出父容器范围)
canvas.style.width = '100%'
canvas.style.height = '100%'
canvas.style.position = 'absolute';
canvas.style.top = '0';
canvas.style.left = '0';
canvas.style.zIndex = '9999';
canvas.style.pointerEvents = 'none';
canvas.style.opacity = '1';
canvas.style.display = 'block';
canvas.width = parentRect.width;
canvas.height = parentRect.height
const ctx = canvas.getContext('2d');
if (!ctx) return;
const canvasWidth = canvas.width;
const canvasHeight = canvas.height * 5;
const fontSize = 24;
const font = `${fontSize}px Arial`;
const color = 'rgba(150, 150, 150, 0.25)';
const angle = -Math.PI / 6;
ctx.font = font;
ctx.fillStyle = color;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.rotate(angle);
let x = 0;
let y = 0;
var line = watermarkText.split('||')
const textWidth = Math.max(...line.map(l => ctx.measureText(l).width));
const textHeight = fontSize * 1.8;
// 调整x的起始位置和增量以适应屏幕宽度
x = -canvasWidth / 2;
while (x < canvasWidth + textWidth) {
y = -canvasHeight / 2;
// 调整y的起始位置和增量以适应屏幕高度
while (y < canvasHeight + textHeight) {
for (let i = 0; i < line.length; i++) {
ctx.fillText(line[i], x, y + i * textHeight);
}
y += textHeight + 80; // 增加水平间距
}
x += textWidth + 80; // 增加垂直间距
}
}
2、app.vue
<template>
<el-main class="framework-main wm-container">
<router-view class="content"></router-view>
<canvas ref="WMCanvas" id="WMCanvas"></canvas>
</el-main>
</template>
<script setup lang="ts">
import { addWatermark } from '@/utils/watermark'
onMounted(() => {
const waterMarkText = `xxxx||===`
if (WMCanvas.value) {
// 添加水印并监听窗口大小变化
addWatermark(WMCanvas.value, waterMarkText)
window.addEventListener('resize', () => {
const canvas = document.getElementById('WMCanvas') as HTMLCanvasElement
if (canvas) {
const ctx = canvas.getContext('2d')
if (ctx) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
}
addWatermark(canvas, waterMarkText)
}
})
// MutationObserver实例監聽樣式是否改變
observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes') {
// 判断是否是style属性的变化
if (mutation.attributeName === 'style') {
if (WMCanvas.value) {
addWatermark(WMCanvas.value, waterMarkText)
}
}
} else if (mutation.type === 'childList') {
// 如果子节点有变化(比如canvas被删除),重新插入canvas
if (WMCanvas.value && !WMCanvas.value.parentElement) {
const parent = document.querySelector('.wm-container')
if (parent) {
parent.appendChild(WMCanvas.value)
// 重新添加水印
addWatermark(WMCanvas.value, waterMarkText)
}
}
}
})
})
// 配置观察选项
const config = { attributes: true, childList: true, subtree: true }
// 开始观察
observer.observe(document.querySelector('.wm-container') ?? document.body, config)
}
// })
})
onUnmounted(() => {
// 组件卸载时停止观察
if (observer) {
observer.disconnect()
}
})
</script>
<style lang="scss" scoped>
.wm-container {
position: relative;
}
</style>