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

明水印

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>
相关推荐
天生我材必有用_吴用9 分钟前
vue3实战九、vue3+vue-cropper实现头像修改
前端
Sobeit17 分钟前
ES2025 颠覆性 JS 黑科技新特性详解
前端
new_abc24 分钟前
net-snmp添加自定义mib树
服务器·前端·javascript
前端梭哈攻城狮30 分钟前
dify二开示例
前端·后端·python
该用户已不存在33 分钟前
Node.js 真的取代了PHP吗?
前端·后端·node.js
ze_juejin42 分钟前
JavaScript 的事件循环(Event Loop)机制
前端
前端缘梦1 小时前
从源码到dist:拆解Webpack如何完成前端工程的"基因编译"
前端·webpack
热爱运维的小七1 小时前
中型企业如何用 RUM 技术破解地理分布式用户体验难题?从指标监测到优化实操
前端·网站响应速度·地域访问
程序猿阿伟1 小时前
《从点击到共鸣:论坛前端如何用交互细节编织用户体验》
前端·ux
樱花开了几轉1 小时前
React中的合成事件解释和理解
前端·javascript·react.js