防止攥改之水印功能组件
防止攥改之水印功能组件
- 效果图
- 逻辑代码
效果图

逻辑代码
<template><div class="containerBox" ref="parentRef" style="height: 300px;background-color: red;"><slot></slot></div>
</template><script setup lang="ts">
// import useWatermarkBg from './useWatermarkBg.js';
import { onMounted, ref, onUnmounted } from 'vue';
const parentRef: any = ref(null)
const props = defineProps({text: {type: String,required: true,default: 'watermark'},fontSize: {type: Number,default: 40},gap: {type: Number,default: 20},textColor:{type: String,required: false,default: 'rgba(0,0,0,0.3)'}
})
let div: any
// canvas画出水印
function useWatermarkBg() {const canvas = document.createElement('canvas')const devicePixelRatio = window.devicePixelRatio || 1const fontSize = props.fontSize * devicePixelRatio;const font = fontSize + 'px serif';const ctx: any = canvas.getContext('2d')// 获取文字高度ctx.font = font;const { width } = ctx.measureText(props.text)const canvasSize = Math.max(100, width) + props.gap * devicePixelRatiocanvas.width = canvasSizecanvas.height = canvasSizectx.translate(canvas.width / 2, canvas.height / 2)ctx.rotate((Math.PI / 180) * -45)ctx.fillStyle = props.textColorctx.font = fontctx.textAlign = 'center'ctx.textBaseline = 'middle'ctx.fillText(props.text, 0, 0)return {base64: canvas.toDataURL(),size: canvasSize / devicePixelRatio}
}
function resetWatermark() {if (!parentRef.value) {return}if (div) {div.remove()}const { base64, size } = useWatermarkBg()div = document.createElement('div')div.style.position = 'absolute'div.style.backgroundImage = `url(${base64})`div.style.backgroundSize = `${size}px ${size}px`div.style.backgroundRepeat = 'repeat'div.style.zIndex = '9999'div.style.inset = '0'parentRef.value.appendChild(div)
}
onMounted(resetWatermark)
// 监听元素变化
const ob = new MutationObserver(entries => {console.log(entries);for(const entry of entries){// removeNodes删除的元素,如果删除的元素是水印元素,则重新画一个for (const dom of entry.removedNodes) {if(dom ==div){resetWatermark()return}}if(entry.target == div){resetWatermark()return}}
})
onMounted(() => {ob.observe(parentRef.value, {childList: true, // 子节点subtree: true, //子树attributes: true // 属性})
})
//组件卸载之后取消
onUnmounted(() => {ob.disconnect()
})
</script><style scoped lang="scss"></style>
相关文章:
防止攥改之水印功能组件
防止攥改之水印功能组件 效果图逻辑代码 效果图 逻辑代码 <template><div class"containerBox" ref"parentRef" style"height: 300px;background-color: red;"><slot></slot></div> </template><script…...
iOS 17 适配 Xcode 15 问题
在适配 iOS 17 xcode 15时遇到的问题,记录一下。 1、 Could not build module ‘WebKit’ type argument nw_proxy_config_t (aka struct nw_proxy_config *) is neither an Objective-C object nor a block type解决方案: 选中不能编译的库的xcodep…...
Element Plus 快速开始
1.完整引入(全局引入) // main.ts import { createApp } from vue import ElementPlus from element-plus import element-plus/dist/index.css import App from ./App.vueconst app createApp(App)app.use(ElementPlus) app.mount(#app) npm install e…...
华为云云耀云服务器L实例评测|StackEdit中文版在线Markdown笔记工具
华为云云耀云服务器L实例评测|StackEdit中文版在线Markdown笔记工具 一、云耀云服务器L实例介绍1.1 云服务器介绍1.2 应用场景1.3 支持镜像 二、云耀云服务器L实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置 三、部署 StackEdit 中文版3.1 StackEdit 介绍3.2 环…...
MyEclipse报错javax/persistence/EntityManagerFactory
MyEclipse报错: Build path is incomplete. Cannot find class file for javax/persistence/EntityManagerFactory 解决方案: 引入依赖 <dependency><groupId>javax.persistence</groupId> <artifactId>persistence-api</a…...
【MySQL进阶】SQL性能分析
一、SQL性能分析 1.SQL执行频率 MySQL 客户端连接成功后,通过 show [session|global] status 命令可以提供服务器状态信 息。通过如下指令,可以查看当前数据库的 INSERT 、 UPDATE 、 DELETE 、 SELECT 的访问频次: -- session 是查看当…...
在SpringBoot项目中整合SpringSession,基于Redis实现对Session的管理和事件监听
1、SpringSession简介 SpringSession是基于Spring框架的Session管理解决方案。它基于标准的Servlet容器API,提供了Session的分布式管理解决方案,支持把Session存储在多种场景下,比如内存、MongoDB、Redis等,并且能够快速集成到Spr…...
浅析vue中computed,method,watch,watchEffect的区别
方法methods只要调用每次都会执行watch(惰性)只有依赖项更新才会执行回调函数,且组件初次渲染不会执行watchEffect:自动追踪依赖变化,只要依赖更新即执行回调函数,且组件初次渲染即执行回调函数computed(惰性): 返回一个只读的ref,具有缓存功…...
activiti7的数据表和字段的解释
activiti7的数据表和字段的解释 activiti7版本有25张表,而activiti6有28张表,activiti5有27张表,绝大部分的表和字段的含义都是一样的,所以本次整理的activiti7数据表和字段的解释,也同样适用于activiti6和5。 1、总览…...
Java手写Trie树和Trie树应用拓展案例
Java手写Trie树和Trie树应用拓展案例 1. 算法思维导图 以下是使用mermaid代码表示的Trie树的实现原理: #mermaid-svg-5twy24X7Wqbhyulb {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-5twy24X7Wqbhyul…...
alova.js快速入门教程
官网地址:Alova.JS - Lightweight request strategy library | Alova.JS 目录 一、alova 是什么? 二、 快速入门 1、安装依赖 (1)使用npm方式安装 (2)使用yarn方式安装 2、在静态 html 中使用 一、al…...
获取IP地址-根据IP获取位置信息
获取外网IP地址,并得到该地址所在位置; 如:101.249.255.255 对应:西藏自治区-拉萨市-堆龙德庆区 string ipAddress GetIPAddress(); string location GetIPLocation(ipAddress); /// <summary>/// 获取IP地址/// </s…...
Android13适配-Google官方照片视频选择器
官方照片选择器 图 1. 照片选择器提供了一个直观的界面,便于与您的应用分享照片。 照片选择器的界面可供浏览和搜索,并按日期降序向用户显示其媒体库中的文件。如隐私保护最佳实践 Codelab 中所示,照片选择器为用户提供了一种安全的内置授权…...
云计算的发展趋势和挑战
本文将探讨云计算的发展趋势和挑战,旨在帮助读者了解云计算的最新动态和未来发展方向。 随着信息技术的发展,云计算作为一种新兴的计算模式,已经得到了广泛的应用和认可。它通过将计算资源、存储资源和应用程序等服务通过互联网提供给用户&a…...
PyG-GAT-Cora(在Cora数据集上应用GAT做节点分类)
文章目录 model.pymain.py参数设置运行图 model.py import torch.nn as nn from torch_geometric.nn import GATConv import torch.nn.functional as F class gat_cls(nn.Module):def __init__(self,in_dim,hid_dim,out_dim,dropout_size0.5):super(gat_cls,self).__init__()s…...
java专项练习(验证码)
package 专题练习;import java.util.Random;public class Developing_CAPTCHA {public static void main(String[] args) {/* 需求:定义方法生成一个5位的验证码 验证码长度为5,前四位为大或小写字母,最后一位是数字*///方法: 如果我们要在一堆没有规律的数据中随机抽取,可以先…...
MS1861 视频处理与显示控制器 HDMI转MIPI LVDS转MIPI带旋转功能 图像带缩放,旋转,锐化
1. 基本介绍 MS1861 单颗芯片集成了 HDMI 、 LVDS 和数字视频信号输入;输出端可以驱动 MIPI(DSI-2) 、 LVDS 、 Mini-LVDS 以及 TTL 类型 TFT-LCD 液晶显示。可支持对输入视频信号进行滤波,图 像增强,锐化,对比度调节&am…...
广州华锐互动:利用VR复原文化遗址,沉浸式体验历史文物古迹的魅力
在过去的几十年里,科技发展飞速,为我们打开了无数新的视角和可能性。其中,虚拟现实(Virtual Reality,简称VR)技术的崭新应用,为我们提供了一种全新的、近乎身临其境的体验历史的方式。本文将重点…...
微信小程序——事件监听
微信小程序是一种轻量级的应用程序,它在移动设备上提供了丰富的用户体验。在开发微信小程序时,事件监听是一项重要的技术,它允许开发者捕捉和处理用户的各种操作。本文将介绍微信小程序事件监听的概念、用法和一些实用示例。 1. 什么是事件监…...
View绘制流程的源码所得
一些问题 子线程可以更新 UI 吗 答案是可以的,在特定的情况下可以 可以先在主线程中调用requestLayout() 方法,然后紧接着在子线程中更新UI(原理:不要在子线程触发 checkThread() 方法,而checkThread() 方法的调用时…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
