vue 水印组件

Watermark.vue

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch } from 'vue';interface Props {text?: string;fontSize?: number;color?: string;rotate?: number;zIndex?: number;gap?: number;
}const props = withDefaults(defineProps<Props>(), {text: 'Watermark',fontSize: 16,color: 'rgba(0, 0, 0, 0.1)',rotate: -45,zIndex: 1000,gap: 100
});const watermarkRef = ref<HTMLDivElement>();
const containerRef = ref<HTMLDivElement>();
let observer: MutationObserver | null = null;
let styleObserver: MutationObserver | null = null;
let securityInterval: number | null = null;const createWatermark = () => {const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');if (!ctx) return '';ctx.font = `${props.fontSize}px Arial`;const textWidth = ctx.measureText(props.text).width;const width = textWidth + props.gap;const height = props.fontSize + props.gap;canvas.width = width;canvas.height = height;ctx.translate(width / 2, height / 2);ctx.rotate((props.rotate * Math.PI) / 180);ctx.font = `${props.fontSize}px Arial`;ctx.fillStyle = props.color;ctx.textAlign = 'center';ctx.textBaseline = 'middle';ctx.fillText(props.text, 0, 0);return canvas.toDataURL();
};const applyWatermark = () => {if (!watermarkRef.value) return;const url = createWatermark();const originalStyles = {position: 'absolute',top: '0',left: '0',width: '100%',height: '100%',pointerEvents: 'none',backgroundImage: `url(${url})`,backgroundRepeat: 'repeat',userSelect: 'none',webkitUserSelect: 'none',zIndex: props.zIndex.toString(),opacity: '1',display: 'block',visibility: 'visible'};Object.assign(watermarkRef.value.style, originalStyles);
};const observeContainer = () => {if (!containerRef.value || !watermarkRef.value) return;observer = new MutationObserver((mutations) => {mutations.forEach((mutation) => {if (mutation.type === 'childList') {const removedNodes = Array.from(mutation.removedNodes);if (removedNodes.includes(watermarkRef.value!)) {containerRef.value?.appendChild(watermarkRef.value!);applyWatermark();}}});});observer.observe(containerRef.value, {childList: true,subtree: true,attributes: true});
};const observeWatermark = () => {if (!watermarkRef.value) return;styleObserver = new MutationObserver(() => {applyWatermark();});styleObserver.observe(watermarkRef.value, {attributes: true,attributeFilter: ['style', 'class']});
};const startSecurityCheck = () => {securityInterval = window.setInterval(() => {if (!watermarkRef.value?.isConnected) {containerRef.value?.appendChild(watermarkRef.value!);}applyWatermark();}, 100) as unknown as number;
};watch(() => [props.text, props.fontSize, props.color, props.rotate, props.gap], () => {applyWatermark();
});onMounted(() => {applyWatermark();observeContainer();observeWatermark();startSecurityCheck();
});onUnmounted(() => {observer?.disconnect();styleObserver?.disconnect();if (securityInterval) {clearInterval(securityInterval);}
});
</script><template><div ref="containerRef" class="watermark-container"><div ref="watermarkRef" class="watermark"></div><div class="content"><slot></slot></div></div>
</template><style scoped>
.watermark-container {position: relative;width: 100%;height: 100%;
}.watermark {position: absolute;top: 0;left: 0;width: 100%;height: 100%;pointer-events: none;background-repeat: repeat;user-select: none;-webkit-user-select: none;
}.content {position: relative;width: 100%;height: 100%;
}
</style>

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

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

相关文章

hbuilder中h5转为小程序提交发布审核

【注意】 [HBuilder] 11:59:15.179 此应用 DCloud appid 为 __UNI__9F9CC77 &#xff0c;您不是这个应用的项目成员。1、联系这个应用的所有者&#xff0c;请求加入项目成员&#xff08;https://dev.dcloud.net.cn "成员管理"-"添加项目成员"&#xff09;…

QT之INI、JSON、XML处理

文章目录 INI文件处理写配置文件读配置文件 JSON 文件处理写入JSON读取JSON XML文件处理写XML文件读XML文件 INI文件处理 首先得引入QSettings QSettings 是用来存储和读取应用程序设置的一个类 #include "wrinifile.h"#include <QSettings> #include <QtD…

道德经总结

道德经 《道德经》是中国古代伟大哲学家老子所著&#xff0c;全书约五千字&#xff0c;共81章&#xff0c;分为“道经”&#xff08;1–37章&#xff09;和“德经”&#xff08;38–81章&#xff09;两部分。 《道德经》是一部融合哲学、政治、人生智慧于一体的经典著作。它提…

行为型:迭代器模式

目录 1、核心思想 2、实现方式 2.1 模式结构 2.2 实现案例 3、优缺点分析 4、适用场景 1、核心思想 目的&#xff1a;将遍历逻辑与数据存储结构解耦 概念&#xff1a;提供一种机制来按顺序访问集合中的各元素&#xff0c;而不需要知道集合内部的构造 举例&#xff1a;…

人脸识别技术合规备案最新政策详解

《人脸识别技术应用安全管理办法》将于2025年6月1日正式实施&#xff0c;该办法从技术应用、个人信息保护、技术替代、监管体系四方面构建了人脸识别技术的治理框架&#xff0c;旨在平衡技术发展与安全风险。 一、明确技术应用的边界 公共场所使用限制&#xff1a;仅在“维护公…

如何把vue项目部署在nginx上

1&#xff1a;在vscode中把vue项目打包会出现dist文件夹 按照图示内容即可把vue项目部署在nginx上

奇好 PDF安全加密 + 自由拆分合并批量处理 OCR 识别

各位办公小能手们&#xff0c;你们好呀&#xff01;今天我要给大家介绍一款超厉害的软件——奇好PDF。它就像是一个PDF文档处理的超级大管家&#xff0c;啥功能都有&#xff0c;格式转换、编辑、提取、安全保护这些统统不在话下&#xff0c;不管是办公、学习&#xff0c;还是设…

Docker-Harbor 私有镜像仓库使用指南

1.用户管理 为项目创建专用用户&#xff0c;并配置权限&#xff0c;确保该用户能够顺利推送镜像到 Harbor 仓库&#xff0c;确保镜像推送操作的安全性和便捷性。 创建完成后可以根据需要选择是否设置为管理员 角色 权限描述 适用场景 系统管理员 拥有系统的完全控制权限 运维…

HomeAssistant开源的智能家居docker快速部署实践笔记(CentOS7)

1. SGCC_Electricity 应用介绍 SGCC_Electricity 是一个用于将国家电网&#xff08;State Grid Corporation of China&#xff0c;简称 SGCC&#xff09;的电费和用电量数据接入 Home Assistant 的自定义集成组件。通过该应用&#xff0c;用户可以实时追踪家庭用电量情况&…

maven 3.0多线程编译提高编译速度

mvn package 默认只使用 单线程 来执行构建生命周期&#xff08;即顺序地构建每一个模块&#xff09;。 如果你使用的是多模块项目&#xff0c;Maven 从 3.0 开始提供了**并行构建&#xff08;parallel build&#xff09;**的能力&#xff0c;但它不是默认开启的。 如何启用多…

python模块管理环境变量

概要 在 Python 应用中&#xff0c;为了将配置信息与代码分离、增强安全性并支持多环境&#xff08;开发、测试、生产&#xff09;运行&#xff0c;使用专门的模块来管理环境变量是最佳实践。常见工具包括&#xff1a; 标准库 os.environ&#xff1a;直接读取操作系统环境变量…

K8s 集群运行时:从 Docker 升级到 Containerd

一、背景&#xff1a;Kubernetes容器运行时演进史 自2020年Kubernetes 1.20版本宣布弃用Docker作为默认容器运行时以来&#xff0c;容器技术生态经历了重大变革。作为CNCF毕业项目&#xff0c;Containerd凭借其轻量化架构、原生CRI支持和卓越性能表现&#xff0c;逐渐成为云原生…

30-消息队列

一、消息队列概述 队列又称消息队列&#xff0c;是一种常用于任务间通信的数据结构&#xff0c;队列可以在任务与任务间、 中断和任务间传递信息&#xff0c;实现了任务接收来自其他任务或中断的不固定长度的消息&#xff0c;任务能够从队列里面读取消息&#xff0c;当队列中的…

AI Agent开发第74课-解构AI伪需求的魔幻现实主义

开篇 🚀在之前的系列中我们狂炫了AI Agent的各种高端操作(向量数据库联动、多模态感知、动态工作流等…),仿佛每个程序员都能用LLM魔法点石成金✨。 但今天咱们要泼一盆透心凉的冷水——当企业把AI当成万能胶水强行粘合所有需求时,连电风扇都能被玩出量子纠缠的魔幻现实…

低代码AI开发新趋势:Dify平台化开发实战

在人工智能快速发展的今天&#xff0c;AI应用的开发方式也在不断演变。从传统的手写代码到如今的低代码甚至零代码开发&#xff0c;技术的进步让更多的非专业开发者也能轻松上手。本文将带你走进Dify平台化开发的世界&#xff0c;探索如何通过这一强大的低代码AI开发平台&#…

开发积累总结

export default 和export const 均用于从模块导出函数、对象或原始值&#xff0c;区别在于&#xff1a; export default&#xff1a;一个文件中只能有一个&#xff0c;为默认导出&#xff0c;在引用时指定名字。 export const&#xff1a;一个文件中有多个&#xff0c;为命名…

【TCP/IP协议族详解】

目录 第1层 链路/网络接口层—帧&#xff08;Frame&#xff09; 1. 链路层功能 2. 常见协议 2.1. ARP&#xff08;地址解析协议&#xff09; 3. 常见设备 第2层 网络层—数据包&#xff08;Packet&#xff09; 1. 网络层功能 2. 常见协议 2.1. ICMP&#xff08;互联网…

vocabulary in program

编号意思&#xff08;英译中&#xff09;音标单词1n. 稀薄&#xff1b;稀罕&#xff1b;珍奇/ˈreərɪsn/rareness2n.登记表&#xff0c;注册簿&#xff1b;注册员&#xff1b;&#xff08;人或乐器的&#xff09;声区&#xff0c;音区&#xff1b;&#xff08;适合特定场合使…

整平机技术进阶:从原理到实战的深度解析

一、整平机的力学原理与数学模型 整平机的核心在于通过材料塑性变形消除内应力&#xff0c;其力学过程可简化为以下模型&#xff1a; 弹塑性变形理论 当材料通过辊轮时&#xff0c;表层受拉应力&#xff0c;芯部受压应力&#xff0c;超过屈服强度后产生永久变形。 关键公式&a…

【b站计算机拓荒者】【2025】微信小程序开发教程 - chapter1 初识小程序 - 3项目目录结构4快速上手

3 项目目录结构 3.1 项目目录结构 3.1.1 目录介绍 # 1 项目主配置文件&#xff0c;在项目根路径下&#xff0c;控制整个项目的-app.js # 小程序入口文件&#xff0c;小程序启动&#xff0c;会执行此js-app.json # 小程序全局配置文件&#xff0c;配置小程序导航栏颜色等信息…