Implementation method of front-end web page watermark

preface

Page watermarking is a means of digital protection, copyright protection and intellectual property protection. In order to prevent others from stealing, it can quickly locate individuals

target

  • To improve security, the hidden watermark cannot be modified through the console
  • The front-end watermark does not affect the normal use of the page
  • The display mode of the front watermark is that the whole page rotates at a certain angle

technical analysis

  • If the front-end web page wants to display the watermark as a whole, first generate a watermark
  • Then fill the whole page with the watermark as the background image (repeat the watermark)
  • Then detect the watermark change, and if the change is regenerated. Will not be hidden.

Implementation scheme

First, a watermark is generated

  • Can be generated through canvas
	function canvasWM({
		container = document.body,
		width = '200px',
		height = '200px',
		textAlign = 'center',
		textBaseLine = 'middle',
		font = '12px SourceHanSansSCVF-Regular',
		fillStyle = 'rgba(0,0,0,0.1)',
		content = 'Front end watermark',
		zIndex = 10
	} = {}) {
		var args = arguments[0];
		var canvas = document.createElement('canvas');
		
		canvas.setAttribute('width', width);
		canvas.setAttribute('height', height);
		var ctx = canvas.getContext('2d');
		
		ctx.textAlign = textAlign;
        ctx.textBaseline = textBaseline;
        ctx.font = font;
        ctx.fillStyle = fillStyle;
        ctx.fillText(content, parseFloat(width) / 2, parseFloat(height) / 2);
		//
        var base64Url = canvas.toDataURL();
	}
 // Calling canvasWM will generate a base64Url watermark image
 

Link: How canvas generates dataUrl

The picture generated by the above code

  • Can be generated by svg (similar to canvas)
	function svgWM({
		container = document.body,
		width = '200px',
		height = '200px',
		fontSize = '12px',
		fontFamily = 'SourceHanSansSCVF-Regular',
		fill= 'rgb(0,0,0,0.06)',
		content = 'Front end watermark',
		zIndex = 10
	} = {}) {
	const args = arguments[0];
	const svgStr = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
		  <text x="50%" y="50%"
		    text-anchor="middle"
            font-family=${fontFamily}
            fill=${fill}
            style="font-size: ${fontSize};">
            ${content}
		  </text>
		</svg>`;
        const base64Url = `data:image/svg+xml;base64,${window.btoa(unescape(encodeURIComponent(svgStr)))}`;
	// Calling svgWM will generate a base64Url watermark image
	}

Using watermark as background image

The above code implements a watermark image, and then creates a div element to take the watermark as the background image

    const __wm = document.querySelector('.__wm');
	const watermarkDiv = __wm || document.createElement("div");
    const styleStr = `
        position:fixed;
        top:0px;
        left:0px;
        width:100%;
        height:1400%;
        z-index:${zIndex};
        pointer-events:none; // The element will never be the target of a mouse event
        background-repeat:repeat; // Repeat watermark display
        transform: rotate(-24deg) translateZ(0); // Overall page rotation angle
        overflow:hidden;
        background-image:url('${base64Url}')`;

    watermarkDiv.setAttribute('style', styleStr);
	watermarkDiv.classList.add('__wm');
	

The rotation in the above code will cause the watermark font on the image to be blurred, which has not been solved for the time being

Detect watermark changes and make adjustments

The MutationObserver interface provides the ability to monitor changes to the DOM tree
The rotation observer API is used to monitor DOM changes. The API can be notified of any changes to the DOM, such as the increase or decrease of nodes, the change of attributes, and the change of text content.
Use the MutationObserver constructor to create a new observer instance. The instance has a callback function that accepts two parameters, the first is the variable array and the second is the observer instance. The observe method of the instance of MutationObserver is used to start listening. It accepts two parameters
The MutationObserver can only detect changes in attributes, addition and deletion of child nodes, etc. there is no way to delete itself. It can meet the requirements by monitoring the parent node

		if (!__wm) {
			container.style.position = 'relative';
		    container.insertBefore(watermarkDiv, container.firstChild);
        }
 		const MutationObserver = window.MutationObserver || 		window.WebKitMutationObserver;
        if (MutationObserver) {
          let mo = new MutationObserver(function () {
            const __wm = document.querySelector('.__wm');
            // Only in__ The wm element is called again only after it changes__ canvasWM
            if ((__wm && __wm.getAttribute('style') !== styleStr) || !__wm) {
              // Avoid constant triggering
              mo.disconnect();
              mo = null;
            __canvasWM(JSON.parse(JSON.stringify(args)));
            }
          });

          mo.observe(container, {
            attributes: true,
            subtree: true,
            childList: true
          })
        }

call

	// Call after import
	canvasWM({
      content: 'QQMusicFE'
    });

Overall code

(function () {
	function svgWM({
		container = document.body,
		width = '200px',
		height = '200px',
		fontSize = '12px',
		fontFamily = 'SourceHanSansSCVF-Regular',
		fill= 'rgb(0,0,0,0.06)',
		content = 'Front end watermark',
		zIndex = 10
	} = {}) {
	const args = arguments[0];
	const svgStr = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
		  <text x="50%" y="50%"
		    text-anchor="middle"
            font-family=${fontFamily}
            fill=${fill}
            style="font-size: ${fontSize};">
            ${content}
		  </text>
		</svg>`;
        const base64Url = `data:image/svg+xml;base64,${window.btoa(unescape(encodeURIComponent(svgStr)))}`;


 	const __wm = document.querySelector('.__wm');
	const watermarkDiv = __wm || document.createElement("div");
    const styleStr = `
        position:fixed;
        top:0px;
        left:0px;
        width:100%;
        height:1400%;
        z-index:${zIndex};
        pointer-events:none; // The element will never be the target of a mouse event
        background-repeat:repeat; // Repeat watermark display
        transform: rotate(-24deg) translateZ(0); // Overall page rotation angle
        overflow:hidden;
        background-image:url('${base64Url}')`;

    watermarkDiv.setAttribute('style', styleStr);
	watermarkDiv.classList.add('__wm');

 if (!__wm) {
          container.style.position = 'relative';
          container.insertBefore(watermarkDiv, container.firstChild);
        }
        
        const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
        if (MutationObserver) {
          let mo = new MutationObserver(function () {
            const __wm = document.querySelector('.__wm');
            // Only in__ The wm element is called again only after it changes__ canvasWM
            if ((__wm && __wm.getAttribute('style') !== styleStr) || !__wm) {
              // Avoid constant triggering
              mo.disconnect();
              mo = null;
            __canvasWM(JSON.parse(JSON.stringify(args)));
            }
          });

          mo.observe(container, {
            attributes: true,
            subtree: true,
            childList: true
          })
        }

      }

      if (typeof module != 'undefined' && module.exports) {  //CMD
        module.exports = __canvasWM;
      } else if (typeof define == 'function' && define.amd) { // AMD
        define(function () {
          return __canvasWM;
        });
      } else {
        window.__canvasWM = __canvasWM;
      }
    })();

Keywords: Javascript Front-end

Added by McInfo on Tue, 08 Mar 2022 11:07:14 +0200