前端水印
canvas添加水印
-
通过canvas生成base64图片,生成一个绝对定位的大小与body一样的div–waterDiv,将waterDiv的背景设置为canvas的base64图片,将waterDiv挂在到body下面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div style='height: 100vh; width: 100%; background-color: red;'></div> <div style='height: 100vh; width: 100%; background-color: yellow;'></div> <div style='height: 100vh; width: 100%; background-color: blue;'></div> <div style='height: 100vh; width: 100%; background-color: black;'></div> </body> <script> function createWaterMark({ container = document.body, width = 200, height = 200, fillStyle = 'rgba(220,220,220)', rotate = '30', zIndex = 100, font = '20px', content = '水印', }) { // 生成canvas const canvas = document.createElement('canvas') // 设置宽高 canvas.setAttribute('width', `${width}px`) canvas.setAttribute('height', `${height}px`) const ctx = canvas.getContext('2d') // 修改样式 ctx.font = font ctx.fillStyle = fillStyle ctx.rotate((Math.PI / 180) * rotate) ctx.fillText(content, parseFloat(width) / 2, parseFloat(height / 2)) // 转成base64 const base64url = canvas.toDataURL() // 生成水印div容器 const waterDiv = document.createElement('div') // 添加样式 waterDiv.setAttribute('style', ` position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: ${zIndex}; background-repeat: repeat; background-image: url('${base64url}'); pointer-events: none; `) container.style.position = 'relative' container.insertBefore(waterDiv, container.firstChild) } createWaterM ark({ content: '这是水印' }) </script> </html>
通过MutationObserver监听水印
-
需要注意的是,通过这种方法虽然可以动态生成水印,但是通过浏览器控制台可以轻易将waterDiv删除,所以还需要监听认为删除水印节点时间以及修改水印样式事件,通过MutationObderver可以实现该功能
-
MutationObserver 是在DOM4中定义的,用于替代 mutation events 的新API,它的不同于events的是,所有监听操作以及相应处理都是在其他脚本执行完成之后异步执行的,并且是所以变动触发之后,将变得记录在数组中,统一进行回调的,也就是说,当你使用observer监听多个DOM变化时,并且这若干个DOM发生了变化,那么observer会将变化记录到变化数组中,等待一起都结束了,然后一次性的从变化数组中执行其对应的回调函数。
-
MutationObserver 的浏览器兼容范围
-
方法
-
构造函数:用来实例化一个Mutation观察者对象,其中的参数是一个回调函数,它是会在指定的DOM节点发送变化后,执行的函数,并且会被传入两个参数,一个是变化记录数组(MutationRecord),另一个是观察者对象本身
new MutationObserver(function(records, itself){});
-
observe
void observe(Node target, optional MutationObserverInit options)
- 其中的可选参数 MutationObserverInit的属性如下:(需要使用的属性添加true即可)
-
childLIst 观察目标节点的子节点的新增和删除。
attributes 观察目标节点的属性节点(新增或删除了某个属性,以及某个属性的属性值发生了变化)。
characterData 如果目标节点为characterData节点(一种抽象接口,具体可以为文本节点,注释节点,以及处理指令节点)时,也要观察该节点的文本内容是否发生变化
subtree 观察目标节点的所有后代节点(观察目标节点所包含的整棵DOM树上的上述三种节点变化)
attributeOldValue 在attributes属性已经设为true的前提下, 将发生变化的属性节点之前的属性值记录下来(记录到下面MutationRecord对象的oldValue属性中)
characterDataOldValue 在characterData属性已经设为true的前提下,将发生变化characterData节点之前的文本内容记录下来(记录到下面MutationRecord对象的oldValue属性中)
attributeFilter 一个属性名数组(不需要指定命名空间),只有该数组中包含的属性名发生变化时才会被观察到,其他名称的属性发生变化后会被忽略想要设置那些删选参数的话
-
disconnect
- 暂定在观察者对象上设置的节点的变化监听,直到重新调用observe方法
-
-
-
使用Mutation Observer监听水印
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div style='height: 100vh; width: 100%; background-color: red;'></div> <div style='height: 100vh; width: 100%; background-color: yellow;'></div> <div style='height: 100vh; width: 100%; background-color: blue;'></div> <div style='height: 100vh; width: 100%; background-color: black;'></div> </body> <script> function createWaterMark({ container = document.body, width = 200, height = 200, fillStyle = 'rgba(220,220,220)', rotate = '30', zIndex = 1000, font = '20px microsoft yahei', content = '水印', }) { // 生成canvas const canvas = document.createElement('canvas') // 设置宽高 canvas.setAttribute('width', `${width}px`) canvas.setAttribute('height', `${height}px`) const ctx = canvas.getContext('2d') // 修改样式 ctx.font = font ctx.fillStyle = fillStyle ctx.rotate((Math.PI / 180) * rotate) ctx.fillText(content, parseFloat(width) / 2, parseFloat(height / 2)) // 转成base64 const base64url = canvas.toDataURL() const waterDiv = document.getElementById('waterDiv') || document.createElement('div') waterDiv.setAttribute('id', 'waterDiv') const style = ` position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: ${zIndex}; background-repeat: repeat; background-image: url('${base64url}'); pointer-events: none; ` // 添加样式 waterDiv.setAttribute('style', style) // 修改父亲节点为相对定位 container.style.position = 'relative' container.insertBefore(waterDiv, container.firstChild) const MutationObserver = window.MutationObserver || window.WebKitMutationObserver if (MutationObserver) { let handle = new MutationObserver(function() { const waterDiv = document.getElementById('waterDiv') // 触发修改时间后添加判断,符合条件时间才重新生成水印 if ((waterDiv && waterDiv.getAttribute('style') !== style) || !waterDiv) { // 断开连接 handle.disconnect(); // 将函数置为空 handle = null; // 重新调用函数 createWaterMark({ container, width, height, fillStyle, rotate, zIndex, font, content, }) } }) // 监听body handle.observe(container, { attributes: true, subtree: true, childList: true }) } } createWaterMark({ content: '这是水印' }) </script> </html>