使用工具
(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>

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注