都2025年了,来看看前端如何给刘亦菲加个水印吧!

前言:图片水印这个东西相信大家都不陌生,前端实现的方式方法也有很多,现在网上流行的无非就是种,一种是纯CSS写,另外一种就是用Canvas。

1.CSS版本

js 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS水印示例</title>
  <style>
    .water_mark {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 1000;
      pointer-events: none;
      opacity: 0.8;
      background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"><text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-size="30" fill="rgba(0,0,0,0.3)">女神刘亦菲~</text></svg>') repeat;
    }
  </style>
</head>

<body>
  <!-- 水印 -->
  <div class="water_mark"></div>
  <img src="./img/lyf.jpg" style="width:100%;height:100vh">
</body>

</html>

效果如下:

优点:

  1. 实现简单
  2. 代码易读性强,适合入门级新手。

缺点:

  1. 可以在浏览器的控制台修改water_mark类样式,如果设置为display:none。水印就去掉了
  2. "水印文本"这几个字不灵活,不好复用。

2.Canvas版本

js 复制代码
<!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>
    * {
      margin: 0;
      padding: 0
    }

    .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>
  <img src="./img/lyf.jpeg" style="width:100%;height:100vh">
  <script>

    function watermark(text) {
      var canvas = document.getElementById('watermarkCanvas');
      var ctx = canvas.getContext('2d');
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
      var width = canvas.width;
      var height = canvas.height;
      ctx.font = '30px Arial';
      ctx.fillStyle = 'rgba(0, 0, 0, 0.8)';
      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();
        }
      }
    }

    window.onload = function () {
      watermark('我爱女神刘亦菲~')
    };
  </script>
</body>

</html>

效果如下:

优点:

  1. 封装一个JS方法能很好的代码复用。
  2. 后续如果扩展,文本样式也可以通过参数的形式传入。

缺点:

  1. dom结构不复杂的情况下,在控制台审查元素还是很容易找到dom结构把它隐藏掉。
  2. 要学习canvas

3.终极版本vue3指令版

js 复制代码
//入口文件main.js
import { watermark } from '@/watermark.js'
const setupAll = async () => {
  const app = createApp(App)
  //...省略
  watermark(app) //全局注册
  app.mount('#app')
}

setupAll()
js 复制代码
  //组件里面使用
 <img src="@/assets/imgs/lyf.png" v-watermark="'我爱女神刘亦菲'" alt="">
js 复制代码
export function watermark(app) {
  app.directive('watermark', (el, binding) => {
   const watermarkText = binding.value || '默认水印';
   const fontSize = 24;
   const fillStyle = 'rgba(0, 0, 0, 0.2)';
   const angle = 45;
   const distance = 200;
   if (el.tagName !== 'IMG') {
     console.warn('v-watermark should be applied on <img> element.');
     return;
   }
   const img = el;
    const processImage = () => {
   if (el._watermarkProcessed) return;
   el._watermarkProcessed = true;
     const canvas = document.createElement('canvas');
     const ctx = canvas.getContext('2d');
     canvas.width = img.naturalWidth;
     canvas.height = img.naturalHeight;
     // 清空画布
     ctx.clearRect(0, 0, canvas.width, canvas.height);
     // 绘制原始图片
     ctx.drawImage(img, 0, 0);
     // 设置水印样式
     ctx.font = `${fontSize}px Arial`;
     ctx.fillStyle = fillStyle;
     ctx.textAlign = 'center';
     ctx.textBaseline = 'middle';
     const radianAngle = (angle * Math.PI) / 180;
     for (let x = -canvas.width; x < canvas.width * 2; x += distance) {
       for (let y = -canvas.height; y < canvas.height * 2; y += distance) {
         ctx.save();
         ctx.translate(x + canvas.width / 2, y + canvas.height / 2);
         ctx.rotate(radianAngle);
         ctx.fillText(watermarkText, 0, 0);
         ctx.restore();
       }
     }
     img.src = canvas.toDataURL('image/png');
   };

   if (img.complete && img.naturalWidth > 0) {
     processImage();
   } else {
     img.addEventListener('load', processImage);
   }
  });

    
}

效果如下:

优点:

  1. 使用简单
  2. 方便复用
  3. 防篡改

总结:

怎么样兄弟们,如果该文章对你有帮助,就请点赞+收藏吧!如果你们项目中也有这种需求。你会使用哪种方式去做呢?欢迎留言讨论~

相关推荐
Spider_Man2 分钟前
🎭 React受控与非受控组件:一场"控制权"的争夺战
前端·react.js
Mintopia7 分钟前
LOD:图形世界里的 “看人下菜碟” 艺术
前端·javascript·计算机图形学
黑客老李9 分钟前
EDUSRC:智慧校园通用漏洞挖掘(涉校园解决方案商)
服务器·前端·网络·安全·web安全
拾光拾趣录10 分钟前
Vue依赖收集机制:响应式原理的核心实现
前端·vue.js
Mintopia11 分钟前
Three.js ArrowHelper:三维世界里的 “方向向导”
前端·javascript·three.js
归于尽12 分钟前
浏览器和 Node.js 的 EventLoop,原来差别这么大
前端·node.js·浏览器
雲墨款哥13 分钟前
Vue 3 路由管理实战:从基础配置到性能优化
前端·vue.js
艾迪的技术之路15 分钟前
redisson使用lock导致死锁问题
java·后端·面试
Jacob023417 分钟前
JavaScript 模块系统二十年:混乱、分裂与出路
前端·javascript
独立开阀者_FwtCoder23 分钟前
Vite Devtools 要发布了!期待
前端·面试·github