主要使用 MutationObserver 监听元素是否被删除或样式被修改,如果有则重新生成水印
一、html部分
<template>
<div ref="parentRef" class="watermark-container">
<slot/>
</div>
</template>
二、js部分
import {computed} from "vue"
export default function useWatermarkBg(props) {
return computed(() => {
const canvas = document.createElement("canvas");
const devicePixelRatio = window.devicePixelRatio || 1;
const fontSize = props.fontSize * devicePixelRatio;
const font = fontSize + "px serif";
const ctx = canvas.getContext("2d");
// 获取文字宽度
ctx.font = font;
const {width} = ctx.measureText(props.text);
const canvasSize = Math.max(100, width) + props.gap * devicePixelRatio;
canvas.width = canvasSize;
canvas.height = canvasSize;
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate((Math.PI / 180) * -45);
ctx.fillStyle = "rgba(0,0,0,0.3)";
ctx.font = font;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(props.text, 0, 0);
return {
base64: canvas.toDataURL(),
size: canvasSize / devicePixelRatio
}
})
}
<script setup>
import useWatermarkBg from "@components/copyright/useWatermarkBg.js";
import {onMounted, onUnmounted, ref} from "vue";
const props = defineProps({
text: {
type: String,
required: true,
default: "watermark"
},
fontSize: {
type: Number,
default: 40,
},
gap: {
type: Number,
default: 10
}
})
const bg = useWatermarkBg(props);
// console.log(bg)
const parentRef = ref(null);
let div;
// 重置水印
function resetWatermark() {
if (!parentRef.value) {
return
}
if (div) {
div.remove();
}
const {base64, size} = bg.value;
div = document.createElement("div");
div.style.position = "absolute";
div.style.backgroundImage = `url(${base64})`;
div.style.backgroundSize = `${size}px ${size}`;
div.style.backgroundRepeat = "repeat";
div.style.zIndex = 9;
div.style.inset = 0;
parentRef.value.appendChild(div)
}
onMounted(resetWatermark);
const ob = new MutationObserver(entries => {
for (const entry of entries){
// 删除节点触发
for(const dom of entry.removedNodes){
if(dom === div){
console.log("水印被删除")
resetWatermark();
return
}
}
// 修改属性触发
if(entry.target === div){
console.log("属性被修改了")
resetWatermark();
return;
}
}
})
onMounted(() => {
// console.log(parentRef.value)
ob.observe(parentRef.value, {
// 监控子节点
childList: true,
// 监控子树
subtree: true,
attributes: true,
})
})
onUnmounted(() => {
ob.disconnect();
})
</script>
三、css部分
<style scoped>
.watermark-container {
width: 100%;
height: 100%;
position: relative;
}
</style>