在网页中添加水印的实现方法

在网页设计中,为了保护内容的版权以及增加一些特殊效果,经常需要在页面上添加水印。本文将介绍一种通过Canvas和JavaScript实现在网页上添加水印的方法。

功能:

  1. 允许自定义水印内容、字体颜色
  2. 可以防止用户删除水印元素、修改样式等其他手段隐藏水印

效果
在这里插入图片描述
代码:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><style>* {margin: 0;padding: 0;}.watermarked {width: 1109px !important;height: 4042px !important;max-width: unset !important;max-height: unset !important;position: absolute !important;top: 0 !important;left: 0 !important;padding: 0 !important;margin: 0 !important;z-index: 11 !important;pointer-events: none !important;background-repeat: repeat !important;opacity: 0.5 !important;display: block !important;visibility: visible !important;clip: initial !important;clip-path: initial !important;transform: initial !important;}</style>
</head><body><div class="div1"><div id="watermark-container" class="watermarked"></div></div><script>document.addEventListener('DOMContentLoaded', function () {ensureWatermarkExists();observeDocument();});function ensureWatermarkExists() {let container = document.getElementById('watermark-container');if (!container) {container = document.createElement('div');container.id = 'watermark-container';document.body.appendChild(container);}resetStyles(container);}function resetStyles(element) {// 定义原始样式const originalStyles = {width: '1109px',height: '4042px',position: 'absolute',top: '0',left: '0',padding: '0',margin: '0',zIndex: '11',pointerEvents: 'none',backgroundRepeat: 'repeat',opacity: '0.5',display: 'block',visibility: 'visible',clip: 'initial',clipPath: 'initial',transform: 'initial'};// 应用原始样式for (const [key, value] of Object.entries(originalStyles)) {element.style[key] = value;}createWatermark();}let originalParentNode = null;  // 用于保存原始的父节点let originalNextSibling = null;  // 用于保存原始的相对位置function ensureWatermarkExists() {let container = document.getElementById('watermark-container');if (!container) {container = document.createElement('div');container.id = 'watermark-container';// 在正确的位置插入if (originalParentNode) {originalParentNode.insertBefore(container, originalNextSibling);} else {// 如果没有原始位置信息,直接添加到文档的末尾document.body.appendChild(container);}}resetStyles(container);}function observeDocument() {const observer = new MutationObserver(function(mutations) {mutations.forEach(function(mutation) {if (mutation.type === 'childList') {let watermarkRemoved = Array.from(mutation.removedNodes).some(node => node.id === 'watermark-container');if (watermarkRemoved) {// 记住原始位置originalParentNode = mutation.target;originalNextSibling = findNextSibling(mutation);console.log('watermark-container 节点被删除,尝试重新创建...');ensureWatermarkExists();}} else if (mutation.type === 'attributes' && mutation.target.id === 'watermark-container') {console.log('watermark-container 样式被修改,尝试重置...');resetStyles(mutation.target);}});});// 配置观察器选项:const config = { childList: true, subtree: true, attributes: true };// 开始观察整个文档observer.observe(document, config);}// 找到下一个兄弟节点function findNextSibling(mutation) {const siblings = Array.from(mutation.target.childNodes);const indexOfRemovedNode = siblings.findIndex(node => node.id === 'watermark-container');return siblings[indexOfRemovedNode + 1];}function createWatermark() {const watermarkText = 'zhangsan(张三)1234332'; // 水印文本const fontSize = 20; // 字体大小const canvas = document.createElement('canvas');fillText(canvas, watermarkText, fontSize);// 将画布作为背景图像应用到容器中const container = document.getElementById('watermark-container');container.style.backgroundImage = `url(${canvas.toDataURL()})`;}function fillText(canvas, txt, fontSize) {const ctx = canvas.getContext('2d');const ratio = window.devicePixelRatio || 1;let width = 300;let height = 300;canvas.width = width;canvas.height = height;canvas.style.width = width + 'px';canvas.style.height = height + 'px';// 计算新字体大小ctx.fillStyle = 'red';ctx.font = fontSize + 'px serif';let textWidth = ctx.measureText(txt).width;let availableWidth = Math.sqrt((width * width) / 2); // 考虑到旋转后的可用宽度let newFontSize = Math.min(fontSize, availableWidth / textWidth * fontSize) * ratio;ctx.font = newFontSize + 'px serif';textWidth = ctx.measureText(txt).width; // 重新计算调整后的文本宽度// 旋转文本ctx.translate(width / 2, height / 2); // 将旋转中心移至画布中心ctx.rotate(-45 * Math.PI / 180); // 旋转 -45 度// 重新定位并填充文本ctx.fillText(txt, -textWidth / 2, newFontSize / 4);}</script>
</body></html>

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

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

相关文章

JNPF开发平台凭什么火?

一、关于低代码 JNPF平台在提供无代码&#xff08;可视化建模&#xff09;和低代码&#xff08;高度可扩展的集成工具以支持跨功能团队协同工作&#xff09;开发工具上是独一无二的。支持简单、快速地构建及不断改进Web端应用程序&#xff0c;可为整个应用程序的生命周期提供全…

Ubuntu18 Opencv3.4.12 viz 3D显示安装、编译、移植

Opencv3.*主模块默认包括两个3D库 calib3d用于相机校准和三维重建 ,viz用于三维图像显示,其中viz是cmake选配。 参考: https://docs.opencv.org/3.4.12/index.html 下载linux版本的源码 sources。 查看cmake apt list --installed | grep cmake 查看vtk apt list --ins…

《白帽子讲web安全》

第十四章 PHP安全 文件包含漏洞是“代码注入”的一种。“代码注入”这种攻击&#xff0c;其原理就是注入一段用户能控制的脚本或代码&#xff0c;并让服务器端执行。“代码注入”的典型代表就是文件包含&#xff08;File Inclusion&#xff09;。文件包含可能会出现在JSP、PHP…

DeepStream--测试TrafficCamNet检测模型

模型地址&#xff1a;https://catalog.ngc.nvidia.com/orgs/nvidia/teams/tao/models/trafficcamnet/version 目前模型是nvidia的加密格式etlt。 nvinfer的配置 [property] gpu-id0 net-scale-factor0.0039215697906911373 tlt-model-keytlt_encode tlt-encoded-modeltraffic…

react等效memo的方法

视频教程 前端技术&#xff5c;Dan博客&#xff5c;在你写memo()之前_哔哩哔哩_bilibili 把与ExpensiveTree的无关的dom做成一个组件 第二种情况&#xff0c;color在ExpensiveTree组件的父级dom 创建一个组件&#xff0c;将state的color和input写上&#xff0c;而ExpensiveTr…

hook io异常注入

文中code https://gitee.com/bbjg001/darcy_common/tree/master/io_hook 需求引入 最近工作需要&#xff0c;需要验证一下我们的服务在硬盘故障下的鲁棒性。 从同事大佬哪里了解到hook技术&#xff0c;可以通过LD_PRELOAD这个环境变量拦截依赖库的调用链&#xff0c;将对标准…

微信小程序记住密码,让登录解放双手

密码是用户最重要的数据&#xff0c;也是系统最需要保护的数据&#xff0c;我们在登录的时候需要用账号密码请求登录接口&#xff0c;如果用户勾选记住密码&#xff0c;那么下一次登录时&#xff0c;我们需要将账号密码回填到输入框&#xff0c;用户可以直接登录系统。我们分别…

OpenCV入门9——目标识别(车辆统计)

文章目录 图像轮廓查找轮廓绘制轮廓轮廓的面积与周长多边形逼近与凸包外接矩形项目总览【车辆统计】视频加载【车辆统计】去背景【车辆统计】形态学处理【车辆统计】逻辑处理【车辆统计】显示信息【车辆统计】 图像轮廓 查找轮廓 # -*- coding: utf-8 -*- import cv2 import n…

Threejs_09 gltf模型的引入(效果初现)

本节使用到的图片、素材、gltf文件&#xff0c;都是老陈打码的原素材 支持&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#x…

SQL DELETE 语句:删除表中记录的语法和示例,以及 SQL SELECT TOP、LIMIT、FETCH FIRST 或 ROWNUM 子句的使用

SQL DELETE 语句 SQL DELETE 语句用于删除表中的现有记录。 DELETE 语法 DELETE FROM 表名 WHERE 条件;注意&#xff1a;在删除表中的记录时要小心&#xff01;请注意DELETE语句中的WHERE子句。WHERE子句指定应删除哪些记录。如果省略WHERE子句&#xff0c;将会删除表中的所…

ANSYS中如何手动为装配体添加接触约束教程

接触的类型&#xff1a; 在接触类型&#xff08;Type&#xff09;选项中&#xff0c;软件共提供了绑定接触&#xff08;Bonded&#xff09;、不分离接触&#xff08;No Separation&#xff09;、无摩擦接触&#xff08;Frictionless&#xff09;、粗糙接触&#xff08;Rough&a…

深入Ansible

1.什么是ansible ansible是新出现的自动化运维工具&#xff0c;基于Python开发&#xff0c;集合了众多运维工具&#xff08;puppet、chef、func、fabric&#xff09;的优点&#xff0c;实现了批量系统配置、批量程序部署、批量运行命令等功能。 ansible是基于 paramiko 开发的…

Linux操作系统使用及C高级编程-D11-D13结构体

由一批数据组合而成的结构型数据。组成结构型数据的每个数据称为结构型数据的“成员”&#xff0c;其描述了一块内存空间的大小及解释意义。 语法&#xff1a; struct 结构体名 { 结构体成员列表 }; 下图是struct的定义和使用方法&#xff0c;其中20行这种赋值方式错误&#xf…

向pycdc项目提的一个pr

向pycdc项目提的一个pr 前言 pycdc这个项目&#xff0c;我之前一直有在关注&#xff0c;之前使用他反编译python3.10项目&#xff0c;之前使用的 uncompyle6无法反编译pyhton3.10生成的pyc文件&#xff0c;但是pycdc可以&#xff0c;但是反编译效果感觉不如uncompyle6。但是版…

BGP笔记

自治系统----AS AS划分的原因&#xff1a;如果网络太大&#xff0c;路由数量进一步增加&#xff0c;路由表规模变得太大&#xff0c;会导致路由收敛速度变慢&#xff0c;设备性能消耗加大&#xff0c;且全网设备对于路由信息的认知不同&#xff0c;造成流量通讯障碍 AS号&…

Django批量插入数据及分页器

文章目录 一、批量插入数据二、分页1.分页器的思路2.用一个案例试试3.自定义分页器 一、批量插入数据 当我们需要大批量创建数据的时候&#xff0c;如果一条一条的去创建或许需要猴年马月 我们可以先试一试for循环试试 我们首先建立一个模型类来创建一个表 models.py&#xff…

腾讯云代金券怎么领取(腾讯云代金券在哪领取)

腾讯云代金券是可抵扣费用的优惠券&#xff0c;领券之后新购、续费、升级腾讯云相关云产品可以直接抵扣订单金额&#xff0c;节省购买腾讯云的费用&#xff0c;本文将详细介绍腾讯云代金券的领取方法和使用教程。 一、腾讯云代金券领取 1、新用户代金券【点此领取】 2、老用户…

【软考】文件的组织结构

目录 一、说明二、逻辑结构2.1 说明2.2 记录式文件2.2.1 说明2.2.2 顺序文件2.2.3 索引文件2.2.4 索引文件 2.3 流式文件 三、物理结构3.1 说明3.2 链接方式之隐式链接3.3 链接方式之显式链接 一、说明 1.组织结构是文件的组织形式。 2.逻辑结构为用户可见的的文件结构。 3.物理…