【VUE】前端实现防篡改的水印

效果

在这里插入图片描述

在这里插入图片描述

水印的作用

图片加水印的操作一般是由后端来完成,有些站点保护的知识产权的类型可能比较多,不仅仅是图片,可能还有视频、文字等等,对于不同类型的对象添加水印后端操作比较复杂,所有有些站点逐步的让前端去进行水印添加的操作。

前端框架

React框架

如果用React框架来进行开发就比较简单,在Ant Design 库里面有一个水印组件Watermark,通过这个组件你可以给一个区域加上一个水印。区域内容没有限制,如图片、文字、视频等等添加水印都是可以的。
在这里插入图片描述

Vue 框架

Ant Design Vue Element UI 暂时没有水印组件。所以需要自己开发,基本思路如下:

  1. 生成水印 :使用canvas.toDataURL()生成base64水印图片数据,将水印图片数据赋值到水印div上。
  2. 防止篡改
    • 监控篡改 : 使用 MutationObserver.observe 监控水印元素、属性、内容、子元素变化,然后改变依赖数据flag.value++;
    • 重新添加水印:定义响应式依赖数据const flag = ref(0);, 使用 watchEffect 自动追踪依赖flag.value;,重新添加水印元素

代码

App.vue

<template>
  <div class="container">
    <WatermarkComponent text="少莫千华">
      <div class="content" style="background-color: red;">
        <img  src="./assets/LA.png"/>
      </div>
    </WatermarkComponent>
    <WatermarkComponent text="少莫千华">
      <video controls class="video" src= './assets/LA.mp4'></video>
    </WatermarkComponent>
  </div>
</template>

<script>
import WatermarkComponent from './components/WatermarkComponent.vue'

export default {
  name: 'App',
  components:{
    WatermarkComponent
  }
}
</script>

<style scoped>
.container{
  width: 100%;
  display: flex;
  justify-content: space-around;
  position: relative;
}
.content{
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  margin: 3px;
}
img{
  height: 100%;
  width: 100%;
  object-fit:cover;
}
video {
  height: 110%;
  width: 100%;
  object-fit:fill;
}
.watermark-container {
  position: relative;
  flex-basis: 50%;
  box-sizing: border-box;
}
video{
  position: absolute;
  flex-basis: 50%;
  box-sizing: border-box;
}

#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

WatermarkComponent.vue

<template>
  <div class="watermark-container" ref="parentRef">
    <slot></slot>
  <!-- 添加一个div,填充整个区域,设置水印背景,重复 -->
  </div>
</template>

<script setup>
import { onMounted, onUnmounted,defineProps, ref, watchEffect } from 'vue';
import useWatermarkBg from './useWatermarkBg';

const props = defineProps( {
  text: {
    type: String,
    required: true,
    default: '少莫千华',
  },
  fontSize:{
    type: Number,
    default: 40,
  },
  gap:{
    type:Number,
    default:20,
  },
});
const bg = useWatermarkBg(props);
const parentRef = ref(null);
// 定义一个依赖
const flag = ref(0);
let div;

//挂载以后添加水印
//监控元素变化、元素属性变化,防止篡改
//动态生成水印元素div
watchEffect(()=>{
  flag.value;
  if(!parentRef.value){
    return ;
  }
  if(div)
  {
    div.remove();
  }
  const {base64,styleSize} = bg.value;
  div = document.createElement('div');
  div.style.backgroundImage = `url(${base64})`;
  div.style.backgroundSize = `${styleSize}px ${styleSize}px`;
  // 重复平铺
  div.style.backgroundRepeat = 'repeat'; 
  // 覆盖到同级的上一个元素
  div.style.zIndex = 9999;
  // 绝对定位
  div.style.position = 'absolute';
  // 设置边距
  div.style.inset = 0;
  //div.style.left = 0;
  //div.style.right = 0;
  //div.style.top = 0;
  //div.style.bottom = 100;
  //将水印添加到 .watermark-container 元素中
  parentRef.value.appendChild(div);
});

onMounted(()=>{
    //监控元素属性、子元素、内容、元素本身变化
    let ob =  new MutationObserver((records)=>{
    console.log(records);
    for(const record of records) {
      // 判断删除的节点
      for(const dom of record.removedNodes) {
        // 判断节点是不是水印
        if(dom === div) {
          //删除水印元素触发 watchEffect
          console.log('删除了水印元素');
          // 修改依赖值,触发 watchEffect 重新运行
          flag.value++;
          return;
        }
      }
      //修改水印元素属性触发 watchEffect
      if(record.target === div){
        console.log('修改了水印属性');
        // 修改依赖值,触发 watchEffect 重新运行
        flag.value++;
        return;
      }
      //生产环境考虑到其他内容,完善,如 ZIndex 等等
    }
  });
  // 监听 parentRef.value的变化
  // 监听内容:childList、attributes、subtree
  ob.observe(parentRef.value,{
    childList: true,
    attributes : true,
    subtree: true,
  });
  onUnmounted(()=>{
    ob && ob.disconnect();//取消监听
    div = null;
  });
});



</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.wartermark-container{
  position: relative;
}
</style>

生成水印图像 useWatermarkBg.js

import { computed } from 'vue';

export default function useWatermarkBg(props) {
  return computed(() => {
    const canvas = document.createElement('canvas');
    const devicePixelRatio = window.devicePixelRatio || 1;
    const fontSize = props.fontSize * devicePixelRatio;
    const font = fontSize + 'px serif';
    const ctx = canvas.getContext('2d');
    // 获取文字宽度
    ctx.font = font;
    const {width} = ctx.measureText(props.text);
    const canvasSize = Math.max(100, width) + props.gap * devicePixelRatio;
    console.log(canvasSize + 'px');
    canvas.width = canvasSize;
    canvas.height = canvasSize;
    ctx.translate(canvas.width/2, canvas.height/2);
    //倾斜文本45°
    ctx.rotate((Math.PI/180) * -45);
    ctx.fillStyle  = 'rgba(0,0,0,0.3)';
    ctx.font = font;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(props.text,0,0);
    return {
      base64:canvas.toDataURL(),
      size:canvasSize,
      styleSize:canvasSize/devicePixelRatio,
    };
  });
}

资源

LA.png

在这里插入图片描述

LA.mp4

演讲开始素材

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/63304.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java 集合框架

Java 集合框架提供了一组接口和类&#xff0c;以实现各种数据结构和算法。 集合框架满足以下几个要求。 该框架必须是高性能的。基本集合&#xff08;动态数组&#xff0c;链表&#xff0c;树&#xff0c;哈希表&#xff09;的实现也必须是高效的。 该框架允许不同类型的集合…

心跳跟随的心形灯(STM32(HAL)+WS2812+MAX30102)

文章目录 前言介绍系统框架原项目地址本项目开发开源地址硬件PCB软件功能 详细内容硬件外壳制作WS2812级联及控制MAX30102血氧传感器0.96OLEDFreeRTOS 效果视频总结 前言 在好几年前&#xff0c;我好像就看到了焊武帝 jiripraus在纪念结婚五周年时&#xff0c;制作的一个心跳跟…

【面试题】 本地运行的前端代码,如何让他人访问?

前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 有时候&#xff0c;我前端写好了项目&#xff0c;想要给其他人看一下效果&#xff0c;可以选择将代码部署到test环境&#xff0c;也可以选择让外部通过i…

RabbitMQ的6种工作模式

RabbitMQ的6种工作模式 官方文档&#xff1a; http://www.rabbitmq.com/ https://www.rabbitmq.com/getstarted.html RabbitMQ 常见的 6 种工作模式&#xff1a; 1、simple简单模式 1)、消息产生后将消息放入队列。 2)、消息的消费者监听消息队列&#xff0c;如果队列中…

rust-异步学习

rust获取future中的结果 两种主要的方法使用 async: async fn 和 async 块 async 体以及其他 future 类型是惰性的&#xff1a;除非它们运行起来&#xff0c;否则它们什么都不做。 运行 Future 最常见的方法是 .await 它。 当 .await 在 Future 上调用时&#xff0c;它会尝试把…

测试岗?从功能测试进阶自动化测试开发,测试之路不迷茫...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 测试新人在想什么…

GD32F103VET输出PWM波形

GD32F103VET将TIMER0_CH3映射到PE14引脚&#xff0c;使其输出PWM波形。测试时&#xff0c;使用示波器看PE14引脚输出的波形&#xff0c;效果更直观。 TIMER0之PWM输出引脚映射如下: TIMER0_REMAP[1:0]"00"(没有映射): TIMER0_CH0默认被映射到PA8引脚 TIMER0_CH1默认…

【51单片机】晨启科技,酷黑版,音乐播放器

四、音乐播放器 任务要求&#xff1a; 设计制作一个简易音乐播放器&#xff08;通过手柄板上的蜂鸣器发声&#xff0c;播放2到4首音乐&#xff09;&#xff0c;同时LED模块闪烁&#xff0c;给人视、听觉美的感受。 评分细则&#xff1a; 按下播放按键A6开始播放音乐&#xff0…

243. 一个简单的整数问题2(树状数组)

输入样例&#xff1a; 10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4输出样例&#xff1a; 4 55 9 15 解析&#xff1a; 一般树状数组都是单点修改、区间查询或者单点查询、区间修改。这道题都是区间操作。 1. 区间修改用数组数组维护差分数组 2. 区间查询&am…

Spring事务(声明式事务)(Spring的事务,Spring隔离级别,事务传播机制)

目录 一、什么是事务&#xff0c;为什么要用事务 二、Spring声明式事务 &#x1f345; 1、Transactional的使用 &#x1f388; 事务回滚 &#x1f388;注意&#xff1a;异常被捕获&#xff0c;不会发生事务回滚 &#x1f345; 2、Transactional 作⽤范围 &#x1f345; …

跨隔离网文件交换,IT部门和业务部门难以兼顾怎么办?

网络隔离技术作为有效的网络安全和数据安全的管理手段&#xff0c;现在已经被充分运用在企业网络建设中。但企业进行网络隔离是基于安全考虑&#xff0c;被隔离的网络间的数据交换需求不会因网络隔离而消失&#xff0c;因此&#xff0c;企业就需要进行隔离网间的数据和文件交换…

element表格+表单+表单验证结合运用

目录​​​​​​​ 一、结果展示 二、实现代码 一、结果展示 1、图片 2、描述 table中放form表单&#xff0c;放输入框或下拉框或多选框等&#xff1b; 点击添加按钮&#xff0c;首先验证表单&#xff0c;如果存在没填的就验证提醒&#xff0c;都填了就向下添加一行表单表…

力扣:54. 螺旋矩阵(Python3)

题目&#xff1a; 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;力扣 示例&#xff1a; 示例 1&#xff1a; 输入&#xff1a;matrix [[1,…

过滤器和拦截器的六大区别

平时觉得简单的知识点&#xff0c;但通常都不会太关注细节&#xff0c;一旦被别人问起来&#xff0c;反倒说不出个所以然来。真的就是一看就会一说就废。下面带大家一起结合实践来区分过滤器和拦截器吧~ 通俗理解&#xff1a; &#xff08;1&#xff09;过滤器&#xff08;Fil…

vue-cli

vue-cli脚手架 案例一&#xff1a; 案例二&#xff1a; 案例三&#xff1a; ​ 一、脚手架简介 Vue脚手架是Vue官方提供的标准化开发工具&#xff08;开发平台&#xff09;&#xff0c;它提供命令行和UI界面&#xff0c;方便创建vue工程、配置第三方依赖、编译vue工程 1. …

2023年华数杯数学建模C题思路 - 母亲身心健康对婴儿成长的影响

# 1 赛题 C 题 母亲身心健康对婴儿成长的影响 母亲是婴儿生命中最重要的人之一&#xff0c;她不仅为婴儿提供营养物质和身体保护&#xff0c; 还为婴儿提供情感支持和安全感。母亲心理健康状态的不良状况&#xff0c;如抑郁、焦虑、 压力等&#xff0c;可能会对婴儿的认知、情…

Centos更换网卡名称为eth0

Centos更换网卡名称为eth0 已安装好系统后需要修改网卡名称为eth0 编辑配置文件将ens33信息替换为eth0,可在vim命令模式输入%s/ens33/eth0/g替换相关内容 修改内核文件,添加内容:net.ifnames=0 biosdevname=0 [root@nova3 ~]# vim /etc/default/grub 使用命令重新生成g…

VLE基于预训练文本和图像编码器的图像-文本多模态理解模型:支持视觉问答、图文匹配、图片分类、常识推理等

项目设计集合&#xff08;人工智能方向&#xff09;&#xff1a;助力新人快速实战掌握技能、自主完成项目设计升级&#xff0c;提升自身的硬实力&#xff08;不仅限NLP、知识图谱、计算机视觉等领域&#xff09;&#xff1a;汇总有意义的项目设计集合&#xff0c;助力新人快速实…

OBS视频视频人物实时扣图方法(四种方式)

图片擦除一些杂乱图像 参考&#xff1a;https://www.bilibili.com/video/BV1va411G7be https://github.com/Sanster/lama-cleaner第一种&#xff1a;色度键选项 第二种&#xff1a;浏览器建立窗口选项 参考视频&#xff1a;https://www.bilibili.com/video/BV1WS4y1C7QY http…

git报错:Error merging: refusing to merge unrelated histories

碰对了情人&#xff0c;相思一辈子。 打命令&#xff1a;git pull origin master --allow-unrelated-histories 然后等一会 再push 切记不要有冲突的代码 需要改掉~