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

html添加水印

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>水印案例</title><style>.box {width: 500px;height: 500px;border: 1px solid #eee;}</style>
</head>
<body><div class="box"><h1>hello world!</h1><p onclick="console.log('123')">我是水印保护的内容</p></div><div class="box"></div>
<script type="text/javascript">
/*** 生成页面水印* 支持:文字数组、base64 图片、HTMLImageElement、图片 URL*/
function createWatermark({texts = ["watermark", "By slongzhang"],fontSize = 12,opacity = 0.1,angle = -20,gapX = 125,gapY = 100,zIndex = 999,id = "slongzhang@126.com",mount = void 0
} = {}) {// ---- 文本模式 ----if (Array.isArray(texts) || typeof texts === "string" && !isImageLike(texts)) {if (typeof texts === "string") texts = [texts];const canvas = document.createElement("canvas");const ctx = canvas.getContext("2d");canvas.width = gapX;canvas.height = gapY;ctx.clearRect(0, 0, gapX, gapY);ctx.globalAlpha = opacity;ctx.font = `${fontSize}px sans-serif`;ctx.fillStyle = "black";ctx.textAlign = "center";ctx.textBaseline = "middle";ctx.translate(gapX / 2, gapY / 2);ctx.rotate((angle * Math.PI) / 180);texts.forEach((t, i) => {ctx.fillText(t, 0, i * (fontSize + 5));});appendWatermark(canvas.toDataURL());return;}// ---- 图片模式 ----loadImage(texts, (img) => {const canvas = document.createElement("canvas");canvas.width = gapX;canvas.height = gapY;const ctx = canvas.getContext("2d");ctx.clearRect(0, 0, gapX, gapY);ctx.globalAlpha = opacity;// 移动到中心再旋转ctx.translate(gapX / 2, gapY / 2);ctx.rotate((angle * Math.PI) / 180);// 缩放比例(保持等比)const scale = Math.min(gapX / img.width, gapY / img.height);const newWidth = img.width * scale;const newHeight = img.height * scale;ctx.drawImage(img, -newWidth / 2, -newHeight / 2, newWidth, newHeight);appendWatermark(canvas.toDataURL());});// ---- 内部函数:挂载水印 ----function appendWatermark(base64Url) {if (!base64Url) return;const div = document.createElement("div");div.style.pointerEvents = "none";div.style.top = "0";div.style.left = "0";div.style.width = "100%";div.style.height = "100%";div.style.position = "fixed";if (zIndex) div.style.zIndex = zIndex;div.style.backgroundImage = `url('${base64Url}')`;let mountType = typeof mount;if (mountType === "undefined") {mount = document.body;} else if (mountType === "string") {mount = document.querySelector(mount);}if (mount && mount instanceof Element) {id = typeof id === "string" ? encodeURI(id) : false;if (id) {const old = mount.querySelector(`div[data-watermark-id="${id}"]`);if (old) old.remove();div.setAttribute("data-watermark-id", id);}if (mount !== document.body) {positionS2T(mount);div.style.position = "absolute";}mount.appendChild(div);}}
}/*** 判断是不是图片输入(base64 / URL / <img> 元素)*/
function isImageLike(input) {if (input instanceof HTMLImageElement) return true;if (typeof input === "string") {return /^data:[a-z]+\/[0-9a-z\-\.\+]+;base64,/.test(input) || /^https?:\/\//.test(input);}return false;
}/*** 加载图片(支持 base64 / URL / <img> 元素)*/
function loadImage(source, callback) {if (source instanceof HTMLImageElement) {if (source.complete) {callback(source);} else {source.onload = () => callback(source);}return;}if (typeof source === "string") {const img = new Image();img.crossOrigin = "anonymous"; // 允许跨域图像img.onload = () => callback(img);img.src = source;}
}/*** 修复父元素 static 定位*/
function positionS2T(parentElement) {if (parentElement instanceof Element &&window.getComputedStyle(parentElement).position === "static") {parentElement.style.position = "relative";}
}</script><script type="text/javascript">
var b64 = `base64的图片资源或图片超链接`;
</script>
<script type="text/javascript">createWatermark({texts: 'slong test', // ["slong watermark", "2025-08-30"],fontSize: 12,opacity: 0.2,angle: -25,gapX: 125,gapY: 100,mount: '.box'});var imgEl = document.createElement('img');imgEl.src = b64;var r = .6createWatermark({texts: imgEl, // b64fontSize: 12,opacity: 0.2,angle: -25,gapX: 125 * r,gapY: 100 * r,mount: document.querySelectorAll('.box')[1]});</script>
</body>
</html>
http://www.xdnf.cn/news/1409275.html

相关文章:

  • 2025年- H103-Lc211--3090. 每个字符最多出现两次的最长子字符串(双指针)--Java版
  • leetcode 268 丢失的数字
  • AG32 Nano开发板的烧录与调试工具(二)
  • 【开题答辩全过程】以 基于vue+springboot的校园疫情管理系统的设计与实现为例,包含答辩的问题和答案
  • 异步编程与面向对象知识总结
  • 家庭全光组网高温故障深度分析与散热重构全记录
  • 【图论】Graph.jl 核心函数
  • 一种使用 Java / Kotlin 编写检测BT种子的磁力链接是否有可用 peers 的程序
  • 扩展:如何设计与实现一个微服务架构下的跨服务异常处理适配器?
  • linux修改权限命令chmod
  • sunset: twilight靶场
  • 利用ms-swift微调和百炼平台微调大模型
  • FTP - 学习/实践
  • 【学习笔记】LLM Interview(Agent相关)
  • (附源码)基于Vue的教师档案管理系统的设计与实现
  • 安装Android Studio
  • centos 7 安装docker、docker-compose教程
  • SketchUp Pro 2024 Mac 3D建模 草图设计大师
  • Redis八股小记
  • 【了解下TJ、TC、TB、TT、TA、qJA、qJC、qJB、YJB、YJT】
  • Asible——将文件部署到受管主机和管理复杂的Play和Playbook
  • [linux仓库]解剖Linux内核:文件描述符(fd)的‘前世今生’与内核数据结构探秘
  • 编写一个用scala写的spark程序从本地读取数据,写到本地
  • 【ArcGIS微课1000例】0150:如何根据地名获取经纬度坐标
  • openssl使用SM2进行数据加密和数据解密
  • 科普:requirements.txt 和 environment.yml
  • Labview使用modbus或S7与PLC通信
  • Machine Learning HW3 report:图像分类(Hongyi Lee)
  • 《深入剖析Kafka分布式消息队列架构奥秘》之Springboot集成Kafka
  • 中级统计师-统计实务-第四章 专业统计