添加水印主要涉及到,首先画出水印图片, 然后生成一个div标签, div的背景为生成的水印图片,之后防止水印标签被改所以需要监测元素,元素变动后删除元素重新添加 。需要注意的是重新添加元素的时候要停止观察器,以及ie删除dom节点有异步会有一点延迟。
class Watermark {
constructor (name, id) {
this.name = name
this.id = id
this.watermarkWithPointerEvents()
}
/**
* 创建标签元素
*/
watermarkWithPointerEvents () {
const src = this.getWatermarkCanvas()
const waterEle = document.createElement('div')
waterEle.style.width = '100%'
waterEle.style.height = '100%'
waterEle.style.pointerEvents = 'none'
waterEle.style.overflow = 'hidden'
waterEle.style.position = 'fixed'
waterEle.style.top = 0
waterEle.style.zIndex = 999
waterEle.style.backgroundImage = `url(${src})`
waterEle.id = 'watermark'
document.body.appendChild(waterEle)
this.watermarkObserver(waterEle)
}
/**
* 绘制水印
*/
getWatermarkCanvas () {
var can = document.createElement('canvas')
var watermarkText = `${this.name}/${this.id}`
can.width = 240
can.height = 300
var ctx = can.getContext('2d')
ctx.font = '32px sans-serif'
ctx.translate(100, 210)
ctx.rotate(-45 * Math.PI / 180)
ctx.fillStyle = 'rgba(0, 0, 0, 0.06)'
ctx.fillText(watermarkText, -40, -30)
return can.toDataURL('image/png')
}
/**
* 监听水印元素
*/
watermarkObserver (targetNode) {
// 检测兼容性 ie支持 11+
const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
if (!MutationObserver) return
const _this = this
// 创建一个观察器实例观察属性变动
const observerTargetAttr = new MutationObserver(function (mutationsList, observer) {
for (let mutation of mutationsList) {
if (mutation.attributeName === 'style' || mutation.attributeName === 'id') {
_this.watermarkModify(targetNode, observer, observerBody)
break
}
}
})
// 创建一个观察器观察节点变动是否删除
const observerBody = new MutationObserver(function (mutationsList, observer) {
for (let mutation of mutationsList) {
[...mutation.removedNodes].some(ele => {
const flag = ele.id === 'watermark'
if (flag) _this.watermarkModify(targetNode, observer, observerTargetAttr)
return flag
})
}
})
// 观察属性
observerTargetAttr.observe(targetNode, {
attributes: true, // 观察属性变动
childList: false, // 观察目标子节点的变化,是否有添加或者删除
subtree: false, // 观察后代节点
attributeFilter: ['style', 'id'] // 筛选需要观察的属性
})
// 观察子元素 (mutationObserver 不支持当前监测当前节点的删除)
observerBody.observe(document.body, {
attributes: false,
childList: true,
subtree: false
})
}
/**
* 水印改变之后删除元素,停止观察,重新添加水印
*/
watermarkModify (targetNode, observer1, observer2) {
// 目标元素改变之后停止观察
observer1 && observer1.disconnect()
observer2 && observer2.disconnect()
// 变动之后删除元素
const Ele = document.getElementById('watermark')
const removeTargetEle = Ele || targetNode;
(removeTargetEle.remove && removeTargetEle.remove()) || (removeTargetEle.removeNode && removeTargetEle.removeNode(true))
// 重新添加水印(ie上删除dom节点会有延迟,添加异步)
setTimeout(() => {
this.watermarkWithPointerEvents()
})
}
}
export default Watermark
// 使用
new Watermark('张三', '123456')