MutationObserver 是一个观察对象,提供用来当DOM树发生变化时开发者能够根据发生的变化,进行逻辑的变化。
就像三体中的水滴同样,当地球上出现大型强子对撞研究时,会触发必定的逻辑来锁死地球的科学研究。git
主要说observe()方法,在实现水印不可删除的过程当中,主要须要应对的逻辑有两个,第一种是对水印节点的修改,第二种是对水印节点的删除。
先说第一种,observe( Node target, optional MutationObserverInit options ),接受两个参数,第一个是目标节点,第二个是目标节点须要被监控的属性,包括属性,子节点,甚至全部后代节点均可以监控。github
drawCanvas() { let divContainer = document.body.appendChild(document.createElement('div')); let waterMarkercanvas = document.createElement('canvas'); let context = waterMarkercanvas.getContext('2d'); divContainer.appendChild(waterMarkercanvas); divContainer.id = 'divContainer' let backgroundUrl = null; divContainer.style.height = window.innerHeight + 'px'; divContainer.style.width = window.innerWidth + 'px'; waterMarkercanvas.width = this.option.canvasWidth; waterMarkercanvas.height = this.option.canvasHeight; context.font =this.option.font; context.textAlign = this.option.textAlign; context.fillStyle = this.option.textStyle; context.translate(waterMarkercanvas.width / 2,waterMarkercanvas.height / 2); context.rotate(this.option.degree * Math.PI / 180); context.fillText(this.option.text, 0, 0); backgroundUrl = waterMarkercanvas.toDataURL('image/png'); divContainer.style.backgroundImage = `url(${backgroundUrl})`; }
在上面的代码里,我首先canvas画出来以后,转为png格式的图片,最后设置成了div的背景图片。canvas
也就是说id为divContainer的div就是我须要监控的dom节点。这时我只须要app
canvasObserver() { this.drawCanvas(); let canvasObserver = new MutationObserver((mo) => { this.drawCnvas(); }); let config = { attributes: true, childList: true, characterData: true }; console.log canvasObserver.observe(document.querySelector('#divContainer'), config); }
就能够实如今用户修改divContainer这个节点是实现canvas的重绘。dom
第二种,由于MutationObserver本山来说,是不支持监控本自己节点的删除操做的,也就是说,我若是删除了divContainer这个节点,是没法实现canvas的重绘的。
那么,这时就须要到一个新的办法了,那就是监控body节点函数
canvasObserver() { this.drawCanvas(); let canvasObserver = new MutationObserver((mo) => { console.log(mo.removeNodes) // this.drawCanvas(); // console.log('detect canvas change and redraw') }); let config = { attributes: true, childList: true, characterData: true }; console.log canvasObserver.observe(document.querySelector('#divContainer').parentNode, config); }
由于在第一段代码中,咱们把该节点做为了body节点的子节点,若是该节点变化,body节点的水滴确定能够检测到,而且完成重绘。由于在咱们的开发中,body节点承载着全部的页面内容,若删除body节点那么也就没有水印的意义了。
这时须要一个就须要一个MutationObserver()中的一个MutationRecord对象。this
能够看到MutationObserver()有一个takeRecords函数来纪录监控中全部节点增查删改的操做,而且返回到MutationRecord对象中。url
能够看到我执行了removeNode的操做而且被记录在了MutationRecord这个对象中。spa
canvasObserver() { this.drawCanvas(); let canvasObserver = new MutationObserver((mo) => { console.log(mo[0].removedNodes) // this.drawCanvas(); // console.log('detect canvas change and redraw') }); let config = { attributes: true, childList: true, characterData: true }; console.log canvasObserver.observe(document.querySelector('#divContainer').parentNode, config); }
这是修改后的代码,咱们只要匹配一个被删除的div和canvas的div是一致的就能够进行下一步的重绘操做了。code
https://github.com/AplloBattl...
这是github地址。