当前位置: 首页 > news >正文

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>

相关文章:

  • 第三十四天打卡
  • 线程的一些基本知识
  • FME入门系列教程7-基于FME的ArcGIS空间数据互操作技术研究与实践
  • 青少年编程与数学 02-020 C#程序设计基础 03课题、开始编程
  • onnx模型转入rknn3399平台上工作记录
  • Axure元件动作五:设置列表选中项
  • 蓝桥杯国14 互质
  • Vue+css实现扫描动画效果(使用@keyframes scan)
  • COZE工作流全场景变现新路径:小程序/网站封装集成
  • SDL2常用函数SDL事件处理:SDL_Event|SDL_PollEvent
  • 如何选择服务器机房托管服务?
  • OpenCV入门
  • Seata分布式事物案例及详解
  • 如何配置jmeter做分布式压测
  • Spring Boot + MyBatis-Plus实现操作日志记录
  • oracle数据库生成awr报告,排查数据库服务器CPU100%,系统卡顿,慢sql,根据sqlid查询关键信息,如会话SID,客户端机器名
  • MySQL 8.0 OCP 1Z0-908 题目解析(11)
  • MySQL 8.0 OCP 1Z0-908 题目解析(13)
  • 游戏引擎学习第307天:排序组可视化
  • 计算机网络学习(三)——HTTP
  • 网站建设安排/自动秒收录网
  • 网站建设 上海交大/搜易网提供的技术服务
  • 软件项目管理系统/青岛seo网络优化公司
  • 网上学编程靠谱吗/武汉seo管理
  • 如何对自己做的php网站加密/直播营销
  • 个人网站建设公司/seo网站优化培训怎么做