前端实现水印的两种方式:SVG 与 Canvas

文章目录

    • 一、为什么要在前端添加水印?
    • 二、两种主流实现方式对比
    • [三、SVG 实现水印(推荐方案)](#三、SVG 实现水印(推荐方案))
      • [✅ 示例源码](#✅ 示例源码)
      • [🔍 关键点说明:](#🔍 关键点说明:)
      • [🧱 优点总结:](#🧱 优点总结:)
    • [四、Canvas 实现水印](#四、Canvas 实现水印)
      • [✅ 示例源码](#✅ 示例源码)
      • [🔍 Canvas 关键技巧:](#🔍 Canvas 关键技巧:)
      • 优点总结:

一、为什么要在前端添加水印?

在现代 Web 页面(尤其是移动端展示场景)中,前端水印 是防止截图、内容盗用的重要手段。它常用于:

  • 🔒 在线预览文档、防截图保护
  • 🧍 用户身份标识(展示用户名称或时间)
  • 📱 移动端页面内容保护
  • 🖼️ 可视化报告防泄露

前端水印的优点:

✅ 实时生成,无需后端参与

✅ 灵活控制文字、样式、透明度

✅ 不影响交互体验

二、两种主流实现方式对比

特性 SVG 水印 Canvas 水印
清晰度 ★★★★★ 高清矢量 ★★★★ 位图缩放可能失真
性能 ★★★★★ 原生渲染 ★★★ 绘制后性能稍低
动态生成 ★★★ 一般 ★★★★★ 灵活绘制
防篡改性 ★★★ ★★★★★
开发复杂度 ★★ 简单 ★★★ 中等

🧠 简单总结:

  • 想快速上水印?👉 用 SVG
  • 想防截图、定制更灵活?👉 用 Canvas

三、SVG 实现水印(推荐方案)

SVG 利用 <pattern> 模式定义一个可重复的图案(比如文字),然后用 <rect> 将它平铺到全屏,性能高、清晰度好,非常适合移动端。

✅ 示例源码

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>SVG 水印示例</title>
    <style>
      body {
        margin: 0;
        font-family: Arial, sans-serif;
        background: #f8f8f8;
        min-height: 100vh;
        overflow-x: hidden;
      }
      .content {
        padding: 20px;
      }
      /* SVG 水印层样式 */
      .svg-watermark {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        pointer-events: none; /* 不影响点击 */
        z-index: 9999;
      }
    </style>
  </head>
  <body>
    <div class="content">
      <h1>SVG 水印实现示例</h1>
      <p>这是一个演示 SVG 水印的页面。无论你滚动、缩放或截图,水印都会保持固定且清晰。</p>
      <p>SVG 方式利用了 pattern 平铺机制,具有高分辨率、低性能损耗等优点,非常适合移动端。</p>
    </div>

    <!-- SVG 水印层 -->
    <svg class="svg-watermark">
      <defs>
        <!-- 定义平铺 pattern -->
        <pattern id="wmPattern" width="180" height="120" patternUnits="userSpaceOnUse" patternTransform="rotate(-30)">
          <!-- 水印文字 -->
          <text x="0" y="60" fill="rgba(0,0,0,0.1)" font-size="16" font-family="Arial">SVG 水印 ©2025</text>
        </pattern>
      </defs>
      <!-- 用矩形填充整个页面 -->
      <rect width="100%" height="100%" fill="url(#wmPattern)" />
    </svg>
  </body>
</html>

🔍 关键点说明:

参数 作用
patternUnits="userSpaceOnUse" 以像素为单位控制平铺间隔
patternTransform="rotate(-30)" 设置整体旋转角度
<text> 定义文字样式,可替换为 <image> 放 logo
pointer-events:none 避免阻挡按钮、输入框操作
fill="rgba(0,0,0,0.1)" 控制透明度(建议 0.05 ~ 0.15)

🧱 优点总结:

✅ 矢量高清,缩放不失真

✅ 性能极高,浏览器原生渲染

✅ 样式灵活,可旋转、平铺、透明化

✅ 兼容所有现代移动浏览器

四、Canvas 实现水印

Canvas 可以直接绘制文字、图像等,并生成水印层。相较于 SVG,它在动态生成(如用户名、时间戳)和防篡改上更强。

✅ 示例源码

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Canvas 水印实现</title>
    <style>
      body {
        margin: 0;
        font-family: Arial, sans-serif;
        background: #fafafa;
        min-height: 100vh;
      }

      .content {
        padding: 20px;
      }

      /* Canvas 水印层 */
      #watermarkCanvas {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        pointer-events: none;
        z-index: 9999;
      }
    </style>
  </head>
  <body>
    <div class="content">
      <h2>Canvas 水印示例</h2>
      <p>Canvas 通过绘制文字并平铺,实现全屏水印。</p>
    </div>

    <canvas id="watermarkCanvas"></canvas>

    <script>
      function createCanvasWatermark(text) {
        const canvas = document.getElementById("watermarkCanvas");
        const ctx = canvas.getContext("2d");

        // 设置 Canvas 尺寸为全屏
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;

        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.font = "16px Arial";
        ctx.fillStyle = "rgba(0,0,0,0.1)";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";

        // 旋转画布实现倾斜水印
        ctx.rotate((-30 * Math.PI) / 180);

        const stepX = 150; // 水印水平间距
        const stepY = 100; // 水印垂直间距

        // 双层循环平铺水印
        for (let x = -canvas.width; x < canvas.width * 2; x += stepX) {
          for (let y = -canvas.height; y < canvas.height * 2; y += stepY) {
            ctx.fillText(text, x, y);
          }
        }
      }

      // 初始化
      createCanvasWatermark("Canvas 水印 ©2025");

      // 监听屏幕大小变化自动重绘
      window.addEventListener("resize", () => createCanvasWatermark("Canvas 水印 ©2025"));
    </script>
  </body>
</html>

🔍 Canvas 关键技巧:

参数 作用
ctx.rotate(-30 * Math.PI / 180) 实现倾斜效果
pointer-events:none 防止遮挡操作
stepX / stepY 控制水印间距
rgba(0,0,0,0.1) 控制透明度
window.resize 响应式刷新

优点总结:

✅ 可动态生成内容(用户名、时间)

✅ 防篡改性更强

✅ 支持图形、渐变等复杂样式

缺点:

  • 缩放后可能轻微模糊(位图特性);

👉点击进入 我的网站

相关推荐
尾善爱看海5 小时前
不常用的浏览器 API —— Web Speech
前端
美酒没故事°6 小时前
vue3拖拽+粘贴的综合上传器
前端·javascript·typescript
一三检测冯野180212918136 小时前
贴合NMPA注册 GB/T5398-2016助力医药包装运输安全
安全·模拟运输测试·包装运输测试·包装振动测试·环境试验·包装跌落测试
jingling5557 小时前
css进阶 | 实现罐子中的水流搅拌效果
前端·css
悟能不能悟8 小时前
前端上载文件时,上载多个文件,但是一个一个调用接口,怎么实现
前端
可问春风_ren9 小时前
前端文件上传详细解析
前端·ecmascript·reactjs·js
羊小猪~~9 小时前
【QT】--文件操作
前端·数据库·c++·后端·qt·qt6.3
晚风资源组10 小时前
CSS文字和图片在容器内垂直居中的简单方法
前端·css·css3
Miketutu11 小时前
Flutter学习 - 组件通信与网络请求Dio
开发语言·前端·javascript