vue3 实现前端生成水印效果

首先一点哈,就是单纯web前端生成水印只能作为警示使用,如果享彻底防住几乎是不可能的,有无数种方式去掉web前端生成的水印,所以这种方式只当是一个君子协议吧。

编写水印组件

首先直接把这部分封装成一个组件吧,我这边直接上代码了。

创建一个 waterMark.vue 文件,用来编写水印组件:

<template><div class="watermark-container" ref="parentRef"><slot></slot></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import useWaterMarkBg from './waterMarkBg';
const props = defineProps({text: {type: String,default: "版权所有"},fontSize: {type: Number,default: 25,},gap: {type: Number,default: 20,},color: {type: String,default: 'rgba(201, 35, 35, 0.5)'}
})let div;
const bg = useWaterMarkBg(props);
const parentRef = ref();const ob = new MutationObserver((entries) => {for (const entry of entries) {for (const node of entry.removedNodes) {if (node === div) {resetWatermark();return;}}if (entry.target === div) {resetWatermark();}}
})onMounted(() => {resetWatermark();ob.observe(parentRef.value, {childList: true,subtree: true,attributes: true,})
})onUnmounted(() => {ob.disconnect();
})// 重置水印
const resetWatermark = () => {if (!parentRef.value) { return }if (div) {div.remove();}const { base64, size } = bg.value.value;div = document.createElement('div');div.style.position = 'absolute';div.style.backgroundImage = `url(${base64})`;div.style.backgroundSize = `${size.width}px ${size.height}px`;div.style.backgroundRepeat = "repeat";div.style.pointerEvents = 'none';div.style.zIndex = '9999';div.style.inset = 0;parentRef.value.appendChild(div);
}</script>
<style scoped lang="scss">
.watermark-container {position: relative;
}
</style>

可以接受四个参数,如果不够可以自己加,分别是 text 水印文本内容fontSize 水印文本大小gap 水印文本间隔color 水印文本颜色

然后在水印组件加载完成的时候调用 resetWatermark 重置水印方法实现添加水印。

水印是动态生成的图片,最后创建了一个动态的div加上页面的,因为还想尽可能的防止一下水印删除,所以说在中途检测了一下dom修改情况,如果修改了,比如删除了div,或者是修改了div的样式,那么就重置水印,重新添加一遍。

其中在组件中还是用了 useWaterMarkBg 方法,下面代码是 waterMarkBg.js 文件的内容,可以根据自己的业务需求适当的修改:

import { ref, computed } from 'vue';/*** 创建水印背景图片的 composable 函数* @param {Object} options - 水印配置选项* @param {string} options.text - 水印文字内容* @param {number} options.fontSize - 字体大小* @param {number} options.gap - 水印间隔* @param {string} options.color - 文字颜色,默认为半透明灰色* @param {number} options.rotate - 旋转角度,默认为 -15 度* @param {string} options.fontFamily - 字体,默认为 Arial* @returns {Object} 返回包含 base64 和 size 的响应式对象*/
function useWaterMarkBg(options = {}) {// 默认参数const defaultOptions = {text: '版权所有',fontSize: 25,gap: 20,color: 'rgba(201, 35, 35, 0.5)',rotate: -15,fontFamily: 'Arial, sans-serif'};// 合并用户参数和默认参数const waterMarkOptions = ref({ ...defaultOptions, ...options });// 计算水印尺寸和 base64 图片const waterMarkInfo = computed(() => {const { text, fontSize, gap, color, rotate, fontFamily } = waterMarkOptions.value;// 创建 canvas 元素const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');if (!ctx) {throw new Error('无法获取 canvas 上下文');}// 设置字体ctx.font = `${fontSize}px ${fontFamily}`;// 获取文字宽度const textWidth = ctx.measureText(text).width;// 计算 canvas 尺寸(包含文字和间隙)const width = textWidth + gap * 2;const height = fontSize * 2 + gap * 2;canvas.width = width;canvas.height = height;// 重置上下文(因为 canvas 尺寸改变了)ctx.font = `${fontSize}px ${fontFamily}`;ctx.fillStyle = color;ctx.textAlign = 'center';ctx.textBaseline = 'middle';// 保存当前状态ctx.save();// 移动到 canvas 中心并旋转ctx.translate(width / 2, height / 2);ctx.rotate((Math.PI / 180) * rotate);// 绘制文字ctx.fillText(text, 0, 0);// 恢复之前的状态ctx.restore();// 转换为 base64const base64 = canvas.toDataURL('image/png');return {base64,size: {width,height}};});// 如果传入的 options 发生变化,可以更新水印function updateOptions(newOptions) {waterMarkOptions.value = { ...waterMarkOptions.value, ...newOptions };}return {value: waterMarkInfo,updateOptions};
}export default useWaterMarkBg;

水印组件的使用

使用的时候就很简单了,引入一下,然后包裹一下需要添加水印的dom就可以了:

    <!-- 默认红色水印 --><water-mark text="严禁传播"><div class="img-con"><img src="../../assets/imgs/watermark/1.jpg" alt="图片1"></div></water-mark><!-- 蓝色水印 --><water-mark text="禁止复制" :fontSize="25" color="rgba(30, 144, 255, 0.3)"><div class="img-con"><img src="../../assets/imgs/watermark/2.jpg" alt="图片2"></div></water-mark><!-- 绿色水印 --><water-mark text="测试水印" :fontSize="25" color="rgba(50, 205, 50, 0.4)"><div class="img-con"><img src="../../assets/imgs/watermark/1.jpg" alt="图片3"></div></water-mark>

效果

在这里插入图片描述

好了,大体就这个样子,还是,水印这个很容易删除,懂得人,删的很快,最好从源头解决,只要后端返回前端的是原文件,那么就可以从浏览器获取到没有水印的内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/98074.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/98074.shtml
英文地址,请注明出处:http://en.pswp.cn/web/98074.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Armonia Mall超级数字生态WEB3商城的引领者

Armonia Mall是一个基于Web3技术的超级数字生态商城&#xff0c;旨在打造全球首家Web3数字普惠商城&#xff0c;帮助千万行销人实现数字生态创业&#xff0c;让全球一亿家庭共享数字经济红利。 Armonia Mall商城创始人&#xff1a;石玉华Armonia Mall七大超级机制&#xff08;模…

Axios与Java Spring构建RESTful API服务集成指南

1 前后端分离时代的技术选择 现在的Web开发&#xff0c;前后端分离已经不是什么新鲜事了。前端用什么&#xff1f;很多团队选择Axios。后端呢&#xff1f;Java Spring依然是企业级应用的首选。 Axios这个JavaScript库确实好用&#xff0c;Promise-based的设计让异步请求变得简单…

Django ORM多对多关系实战指南

一、Django 多对多关系的原理 在关系型数据库中&#xff0c;多对多关系通常需要 第三张中间表 来维护两张表之间的对应关系。 在 Django 中&#xff0c;你只需要定义 ManyToManyField&#xff0c;Django 会自动帮你创建这张中间表。 特点&#xff1a; 可以双向查询&#xff08;…

STM32 单片机开发 - TIM 定时器(PWM)

一、硬件定时器高级控制定时器 Advanced Control Timers (TIM1/TIM8)通用定时器 General Purpose Timers (TIM2/TIM3/TIM4/TIM5)通用定时器 General Purpose Timers (TIM15/TIM16/TIM17)基本定时器 Basic Timers (TIM6/TIM7)表 1 定时器种类二、TIM 中 PWM 概念PWM 的基本原理就…

OpenCV内置分类器实现简单的人脸识别

引言 人脸检测是计算机视觉领域的基础任务之一&#xff0c;广泛应用于安防监控、人机交互、图像美化等场景。今天我们将通过一段简洁的Python代码&#xff0c;使用OpenCV库实现实时摄像头人脸检测功能。无论你是计算机视觉新手还是有经验的开发者&#xff0c;这篇文章都能帮你理…

Tomcat 性能优化与高并发调优

Tomcat 性能优化与高并发调优1. 引言 经过前几篇文章的学习&#xff0c;我们已经掌握了 Tomcat 的核心原理&#xff1a; Connector 连接器容器体系&#xff08;Engine → Host → Context → Wrapper&#xff09;Servlet 执行链路线程模型&#xff08;Executor Worker&#xf…

MacOS M1安装face_recognition

MacOS M1安装face_recognition一致失败&#xff0c;尝试网上各种方法还是失败&#xff0c;遂分享自己安装成功的经历。 conda虚拟环境python版本&#xff1a;3.9.23准备工作确保 Homebrew 已安装 Homebrew 是 macOS 的包管理器&#xff0c;用于安装依赖项。如果尚未安装&#x…

动态库和静态库的链接加载

静态库的链接与加载静态库&#xff08;如.a或.lib文件&#xff09;在编译时直接链接到可执行文件中。编译器会将静态库中实际用到的代码复制到最终的可执行文件&#xff0c;生成独立的二进制文件。优点是不依赖外部库文件&#xff0c;但会导致可执行文件体积较大。生成静态库的…

如何处理在pytorch环境中已经安装的matplotlib无法使用的问题

1 问题已经安装好的matplotlib包无法在pytorch环境中使用。2 方法方法一&#xff1a;用命令安装matplotlib &#xff1a;方法二&#xff1a;打开cmd&#xff0c;使用conda install matplotlib命令安装matplotlib库#输入以下代码段&#xff0c;查询当前执行路径import osos.sys.…

Linux基础命令汇总

系统基础指令 ls:列出目录内容 ls -a:显示所有文件(包括隐藏文件) ls -l:显示详细文件信息 ls /etc:列出 /etc 目录内容 示例: cat:查看文件内容 cat /etc/os-release:查看系统版本信息 cat file1:显示文件内容 cat file1 file2 > merged.txt:合并文件并输出到新…

一场史诗级的冒险——Docker命令大航海!

各位亲爱的开发者、运维勇士、以及所有对现代化软件部署充满好奇的小伙伴们&#xff01;今天&#xff0c;我们将开启一场史诗级的冒险——Docker命令大航海&#xff01;我们将乘坐“Docker号”巨轮&#xff0c;驶向容器化技术的星辰大海。 这不是一篇枯燥的说明书&#xff0c;而…

告别依赖混乱:Spring IoC 容器与 DI 依赖注入入门精讲

目录 什么是 IoC IoC 介绍 传统开发思路 解决方法 IoC 优势 DI IoC & DI 使用 IoC 详解 Bean 的存储 Controller&#xff08;控制器存储&#xff09; 获取 bean 对象的其他方法 bean 命名 面试题之 ApplicationContext pk BeanFactory Service&#xff08;服…

视频理解学习笔记

目录 VideoRefer VideoPrism 核心解密&#xff1a;通用视频编码器的力量 VideoRefer VideoRefer 是由浙江大学和阿里达摩院联合推出的视频对象感知与推理技术&#xff0c;增强视频大型语言模型&#xff08;Video LLMs&#xff09;的空间-时间理解能力。简单一点来说就是可以…

P1198题解

题目链接 开题第一件事看数据范围.这里的范围是二十万,支持O(nlogn). 这是一个RMQ问题,同时要加点,我们因此考虑ST表或者线段树.这里用线段树是核弹打蚊子,没有意义,我们因此考虑ST表.我们注意到如果加点操作需要改动ST表原来的东西ST表就会炸掉,我们就要考虑更高级的数据结构…

使用yolov8对视频进行目标检测

使用 Ultralytics 的 YOLO 模型对视频进行逐帧目标检测非常简单&#xff0c;以下是完整的实现方法&#xff1a; 我们的输入视频是这样的 视频目标检测输入视频这里是天津市和平区天津大学附近&#xff0c;感兴趣的小伙伴来天津玩哈&#xff01;&#xff01; 1. 安装依赖 确保已…

Edge浏览器的自动化点击系统

Tag_click_openclose_V6 开发与使用注意事项 网页自动化点击系统 一个基于Python和CustomTkinter开发的桌面应用程序&#xff0c;通过Selenium实现对Edge浏览器的自动化控制。点击Tag_click_openclose_V6进入Github自取&#xff0c;记得点赞收藏嗷。 功能介绍 连接到已打开…

Python股票数据分析与预测系统 LSTM神经网络算法 股票价格预测 Tensorflow深度学习 机器学习 Flask框架 东方财富(建议收藏)✅

博主介绍&#xff1a;✌全网粉丝50W&#xff0c;前互联网大厂软件研发、集结硕博英豪成立软件开发工作室&#xff0c;专注于计算机相关专业项目实战6年之久&#xff0c;累计开发项目作品上万套。凭借丰富的经验与专业实力&#xff0c;已帮助成千上万的学生顺利毕业&#xff0c;…

英莱科技焊缝跟踪系统亮相德国埃森焊接展,激光视觉点亮世界舞台

9月15-19日&#xff0c;每4年一届的德国埃森焊接与切割展览会&#xff08;SCHWEISSEN & SCHNEIDEN&#xff09;即将盛大开幕。作为焊接行业最具规模及权威性的盛会之一&#xff0c;英莱科技将携全新PF系列激光视觉焊缝跟踪系统惊艳亮相&#xff0c;为全球智能化焊接贡献中国…

嵌入式基本概念:什么是指令集,微架构,IDE,DFP等等是什么意思,有什么关系???

注&#xff1a;下面是指令集和微框架的分类图&#xff0c;后面我会以ARM的M4举例子。 一.什么是指令集 大概的可以看这个视频 https://www.bilibili.com/video/BV1uXzbYBEy2/?spm_id_from333.1007.top_right_bar_window_custom_collection.content.click&vd_source406ed…

Spring Cloud之服务入口Gateway之自定义过滤器

目录 过滤器执行顺序 自定义过滤器 自定义GatewayFilter 定义GatewayFilter 配置过滤器 启动服务并访问 自定义GlobalFilter 定义GlobalFilter 启动服务并访问 服务部署 过滤器执行顺序 如果⼀个项⽬中, 既有GatewayFilter, ⼜有 GlobalFilter时, 执⾏的先后顺序是什…