2026/1/12 8:23:29
网站建设
项目流程
网络直播网站建设,wordpress新闻资讯主题,网站建设 超薄网络,广告文案生成器在前端开发中#xff0c;网页水印是一个非常常见的需求#xff0c;主要用于环境标识#xff08;如测试环境、生产环境#xff09;、版权保护、数据安全等场景。一个合格的网页水印需要满足防删除、自适应窗口、高兼容性等特性#xff0c;本文将基于 Canvas DOM 监听的方式…在前端开发中网页水印是一个非常常见的需求主要用于环境标识如测试环境、生产环境、版权保护、数据安全等场景。一个合格的网页水印需要满足防删除、自适应窗口、高兼容性等特性本文将基于 Canvas DOM 监听的方式实现一个健壮的网页水印工具并结合 Vue 项目演示实际使用流程。一、核心实现思路网页水印的核心实现逻辑分为以下几步Canvas 生成水印图片利用 Canvas 绘制水印文字支持旋转、透明度、字体样式并转换为 Base64 格式的图片。DOM 挂载水印容器创建一个全屏的 div 容器将 Canvas 生成的图片作为背景图挂载到页面根节点document.documentElement确保水印覆盖整个页面。防删除机制通过定时检测水印元素是否存在若被删除则重新生成同时使用随机 ID 自定义属性双重标记水印元素提升防删除能力。自适应处理监听窗口大小变化当窗口缩放时重新生成水印保证水印布局不会错位。兼容性处理添加 try-catch 捕获异常如 Canvas 的 toDataURL 方法被 CSP 限制兼容不同浏览器和页面环境。二、完整代码实现水印工具类我们将水印功能封装为一个独立的工具类watermark.js便于在项目中复用/** * 网页水印工具类 * 功能生成防删除、自适应、高兼容性的网页水印 * 作者前端无涯https://blog.csdn.net/weixin_44439817?typeblog * 日期2025-12-15 */letwatermark{}/** * 生成水印元素并挂载到页面 * param {string} str - 水印显示的文字内容 * returns {string|null} - 水印元素的ID失败返回null */letsetWatermark(str){// 生成随机ID防止被反调试脚本通过固定ID清除letidwm-Math.random().toString(36).substr(2,9)try{// 1. 创建Canvas元素绘制水印文字letcandocument.createElement(canvas)// 设置Canvas尺寸水印的单个重复单元大小can.width200can.height150letcanscan.getContext(2d)// 文字旋转-20度斜向显示cans.rotate(-20*Math.PI/180)// 文字样式字体、透明度、颜色cans.font20px Verdanacans.fillStylergba(100, 100, 100, 0.2)// 文字对齐方式cans.textAlignleftcans.textBaselinemiddle// 绘制文字位置Canvas宽/8高/2cans.fillText(str,can.width/8,can.height/2)// 2. 创建水印容器divletdivdocument.createElement(div)div.idid// 添加自定义属性用于双重检测水印元素div.setAttribute(data-watermark,true)// 3. 设置水印容器样式全屏覆盖、层级最高、不可点击div.style.pointerEventsnone// 防止水印遮挡页面元素的点击事件div.style.top0pxdiv.style.left0pxdiv.style.positionfixed// 固定定位跟随窗口滚动div.style.zIndex2147483647// 最高层级确保覆盖所有元素div.style.width100vw// 视口宽度div.style.height100vh// 视口高度div.style.displayblock !important// 强制显示div.style.visibilityvisible !important// 强制可见// 4. 将Canvas图片设置为背景图兼容CSP限制添加try-catchtry{div.style.backgroundurl(can.toDataURL(image/png)) left top repeat}catch(e){console.error(Watermark canvas toDataURL error:,e)}// 5. 挂载到documentElement比body更稳定避免body被样式限制document.documentElement.appendChild(div)console.log(Watermark element appended:,id)returnid}catch(err){console.error(Watermark creation failed:,err)returnnull}}/** * 初始化水印对外暴露的方法仅允许有效调用一次 * param {string} str - 水印文字内容 */watermark.set(str){// 延迟执行1秒确保DOM完全加载后再生成水印setTimeout((){letcurrentIdsetWatermark(str)// 定时检测每2秒防止水印被删除或隐藏setInterval((){// 检测方式1通过ID判断水印元素是否存在if(currentIddocument.getElementById(currentId)null){console.warn(Watermark removed, recreating...)currentIdsetWatermark(str)}// 检测方式2通过自定义属性双重验证防止ID被篡改constwmdocument.querySelector(div[data-watermarktrue])if(!wm){currentIdsetWatermark(str)}},2000)// 窗口大小变化时重新生成水印自适应window.onresize(){// 仅当水印不存在时重建避免频繁操作导致闪烁if(currentIddocument.getElementById(currentId)null){setWatermark(str)}}},1000)// 延迟1秒确保页面DOM渲染完成}exportdefaultwatermark三、Vue 项目中使用水印工具以 Vue 2/3 项目为例我们在根组件App.vue中引入并使用水印工具实现全局水印效果template div idapp !-- 路由视图 -- router-view / /div /template script // 引入水印工具类 import watermark from /utils/watermark export default { name: App, components: { ThemePicker }, // 挂载完成后初始化水印 mounted() { // 设置水印内容这里为“测试环境”可根据环境动态传入如生产环境、开发环境 watermark.set(测试环境-前端无涯) } } /script style scoped /* 示例样式隐藏主题选择器可根据项目情况删除 */ #app .theme-picker { display: none; } /style四、关键优化点解析本文的水印方案相比传统实现做了以下关键优化提升了健壮性和兼容性1.防删除机制升级随机 ID水印元素的 ID 使用wm- 随机字符串生成避免被攻击者通过固定 ID 直接删除。双重检测定时检测时既通过 ID 检查又通过自定义属性data-watermarktrue检查即使 ID 被篡改也能检测到水印被删除。定时重建每 2 秒检测一次若水印被删除则立即重新生成让攻击者的删除操作失效。2.兼容性提升挂载到document.documentElement相比挂载到bodydocumentElementhtml 标签更稳定不会因body的样式如overflow: hidden、position: relative导致水印显示异常。try-catch 捕获异常包裹 Canvas 的toDataURL方法防止因页面 CSP内容安全策略限制导致水印生成失败。延迟执行初始化水印时延迟 1 秒执行确保页面 DOM 完全加载后再生成水印避免因 DOM 未加载完成导致挂载失败。3.用户体验优化pointer-events: none水印容器设置该样式不会遮挡页面元素的点击、hover 等交互事件不影响用户操作。固定定位 视口尺寸使用position: fixed100vw/100vh确保水印覆盖整个视口且跟随窗口滚动。resize 自适应监听窗口大小变化仅在水印不存在时重建避免频繁操作导致水印闪烁。4.样式强制生效水印容器设置display: block !important和visibility: visible !important防止被攻击者通过样式隐藏水印。五、常见问题与解决方案在实际使用中可能会遇到以下问题可参考对应解决方案1.水印不显示检查 Canvas 绘制是否正常可在控制台打印can.toDataURL(image/png)查看是否生成有效的 Base64 字符串。检查水印容器的 z-index确保 z-index 足够高本文使用 2147483647是浏览器允许的最大安全值未被其他元素覆盖。检查页面 CSP 策略若控制台报错toDataURL is not allowed需在服务端配置 CSP 策略允许data:协议。2.水印被遮挡检查水印容器的position确保为fixed而非absoluteabsolute 会受父元素定位影响。检查页面元素的 z-index若某些元素的 z-index 超过 2147483647可适当提高水印的 z-index但不建议超过浏览器最大值或调整页面元素的 z-index。3.窗口缩放后水印错位本文的方案已监听window.onresize事件在窗口缩放时重新生成水印若仍出现错位可将resize事件的处理逻辑改为立即重建水印而非仅在不存在时重建window.onresize(){currentIdsetWatermark(str)// 直接重建}六、扩展功能可选根据实际需求可对水印工具进行扩展自定义水印样式将字体、颜色、透明度、旋转角度等参数作为配置项传入支持自定义水印样式。多行水印文字修改 Canvas 绘制逻辑支持多行文字水印。动态修改水印内容添加watermark.update(str)方法支持运行时动态修改水印文字。图片水印在 Canvas 中绘制图片实现图片 文字组合水印。七、总结本文实现的网页水印方案通过 Canvas 生成水印图片结合 DOM 监听和定时检测机制实现了防删除、自适应、高兼容性的核心需求。该方案已在 Vue 项目中验证可直接复用至 React、Angular 等前端框架也可用于纯 HTML/JS 项目。在实际项目中可根据环境如开发、测试、生产动态传入水印内容进一步提升水印的实用性。同时建议结合后端接口获取用户信息如用户名、工号作为水印内容实现更精细化的版权保护。