都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. 防篡改

总结:

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

相关推荐
zwjapple6 小时前
docker-compose一键部署全栈项目。springboot后端,react前端
前端·spring boot·docker
像风一样自由20208 小时前
HTML与JavaScript:构建动态交互式Web页面的基石
前端·javascript·html
aiprtem9 小时前
基于Flutter的web登录设计
前端·flutter
浪裡遊9 小时前
React Hooks全面解析:从基础到高级的实用指南
开发语言·前端·javascript·react.js·node.js·ecmascript·php
why技术9 小时前
Stack Overflow,轰然倒下!
前端·人工智能·后端
幽络源小助理9 小时前
SpringBoot基于Mysql的商业辅助决策系统设计与实现
java·vue.js·spring boot·后端·mysql·spring
GISer_Jing9 小时前
0704-0706上海,又聚上了
前端·新浪微博
止观止9 小时前
深入探索 pnpm:高效磁盘利用与灵活的包管理解决方案
前端·pnpm·前端工程化·包管理器
whale fall9 小时前
npm install安装的node_modules是什么
前端·npm·node.js
烛阴9 小时前
简单入门Python装饰器
前端·python