前端面试宝典---前端水印

明水印

1. 背景图

通过css的background-image加载背景图

2. canvas+background水印

前端水印实现思路与示例代码

一、核心实现思路
  1. Canvas动态生成水印

    通过Canvas绘制文本或图案,将生成的图像转为Base64格式,作为背景图重复平铺到目标元素上。例如:

    javascript 复制代码
    function createWatermark(text) {
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      canvas.width = 200;
      canvas.height = 150;
      ctx.font = '12px Arial';
      ctx.fillStyle = 'rgba(200,200,200,0.2)';
      ctx.rotate(-30 * Math.PI / 180); // 倾斜角度
      ctx.fillText(text, 10, 100);
      return canvas.toDataURL('image/png');
    }
  2. 防篡改机制

    • 使用MutationObserver监听DOM变化,若水印元素被删除则重新注入
    • 禁止控制台操作:禁用右键菜单、屏蔽开发者工具快捷键
    javascript 复制代码
    document.addEventListener('contextmenu', e => e.preventDefault());
  3. 容器绑定

    将水印作为独立图层覆盖在目标内容上方,通过CSS确保全屏状态仍可见:

    css 复制代码
    .watermark-container {
      position: relative;
    }
    .watermark-layer {
      position: absolute;
      pointer-events: none;
      z-index: 9999;
      background: url('data:image/png;base64,...');
    }
二、完整示例代码
html 复制代码
<!DOCTYPE html>
<html>

<body>
  <style>
    .watermark-container {
      position: relative;
    }

    .watermark-layer {
      position: absolute;
      pointer-events: none;
      z-index: 9999;
      background: url('data:image/png;base64,...');
    }
  </style>
  <div id="content">需要保护的内容</div>

  <script>
    function createWatermark (text) {
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      canvas.width = 200
      canvas.height = 150
      ctx.font = '12px Arial'
      ctx.fillStyle = 'rgba(200,200,200,0.2)'
      ctx.rotate(-30 * Math.PI / 180) // 倾斜角度
      ctx.fillText(text, 10, 100)
      return canvas.toDataURL('image/png')
    }

    function initWatermark (text = '机密文件') {
      const watermark = document.createElement('div')
      watermark.style.backgroundImage = `url(${createWatermark(text)})`
      watermark.style.position = 'fixed'
      watermark.style.top = 0
      watermark.style.bottom = 0
      watermark.style.right = 0
      watermark.style.left = 0

      watermark.style.pointerEvents = 'none'

      // 防删除监听
      const observer = new MutationObserver(mutations => {
        if (!document.contains(watermark)) {
          document.body.appendChild(watermark)
        }
      })
      observer.observe(document.body, { childList: true })

      document.body.appendChild(watermark)
    }

    initWatermark('严禁复制');
  </script>
</body>

</html>
三、注意事项
  1. 动态水印

    可添加时间戳、用户ID等可变信息增强追踪能力:

    javascript 复制代码
    const dynamicText = `${username} ${new Date().toLocaleString()}`;
  2. 样式优化

    • 使用background-repeat: repeat平铺
    • 调整rgba透明度值平衡可见性与内容遮挡
  3. 跨框架实现

    Vue/React可通过高阶组件封装水印逻辑,例如:

    js 复制代码
    const withWatermark = (Component) => (props) => (
      <div className="watermark-wrapper">
        <Component {...props} />
      </div>
    )

纯canvas水印

javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Canvas水印示例</title>
  <style>
    .watermark {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 1000;
      pointer-events: none;
      opacity: 0.2;
    }
  </style>
</head>
<body>
  <canvas id="watermarkCanvas" class="watermark"></canvas>
  <div>
    <h1>内容区域</h1>
    <p>这是需要加水印的内容</p>
  </div>
  <script>
    window.onload = function() {
      var canvas = document.getElementById('watermarkCanvas');
      var ctx = canvas.getContext('2d');
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;

      var text = '水印文本';
      var width = canvas.width;
      var height = canvas.height;
      ctx.font = '30px Arial';
      ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';

      // 旋转并重复绘制水印文本
      for (var x = 0; x < width; x += 200) {
        for (var y = 0; y < height; y += 200) {
          ctx.save();
          ctx.translate(x, y);
          ctx.rotate(- Math.PI / 4);
          ctx.fillText(text, 0, 0);
          ctx.restore();
        }
      }
    };
  </script>
</body>
</html>

svg水印

javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>SVG水印示例</title>
  <style>
    .watermark {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 1000;
      pointer-events: none;
      opacity: 0.2;
    }
  </style>
</head>
<body>
  <div class="watermark">
    <svg width="100%" height="100%">
      <text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-size="30" fill="rgba(0,0,0,0.1)" transform="rotate(-45, 50, 50)">水印文本</text>
    </svg>
  </div>
  <div>
    <h1>内容区域</h1>
    <p>这是需要加水印的内容</p>
  </div>
</body>
</html>
相关推荐
站在风口的猪11085 分钟前
《前端面试题:前端布局全面解析(圣杯布局、双飞翼布局等)》
前端·css·html·css3·html5
IT瘾君6 分钟前
JavaWeb:前后端分离开发-部门管理
开发语言·前端·javascript
mldong17 分钟前
我的全栈工程师之路:全栈学习路线分享
前端·后端
江城开朗的豌豆36 分钟前
JavaScript篇:"闭包:天使还是魔鬼?6年老司机带你玩转JS闭包"
前端·javascript·面试
早知道不学Java了38 分钟前
chromedriver 下载失败
前端·vue.js·react.js·npm·node.js
江城开朗的豌豆1 小时前
JavaScript篇:解密JS执行上下文:代码到底是怎么被执行的?
前端·javascript·面试
EndingCoder2 小时前
React从基础入门到高级实战:React 高级主题 - React 微前端实践:构建可扩展的大型应用
前端·javascript·react.js·前端框架·状态模式
BigTopOne3 小时前
【ijkplayer】 android 初始化硬解码
前端
1024小神3 小时前
rust或tauri项目执行命令的时候,cmd窗口也会弹出显示解决方法
前端·javascript
橙某人3 小时前
🤝和Ollama贴贴!解锁本地大模型的「私人订制」狂欢🎉
前端·deepseek