We from the implementation of the way to consider, since we want to do watermark, it must be full screen, we will first think of a few points

  1. Fixed with a div full screen.
  2. The watermark is bound to the login information, so we get the account information from the cookie.
  3. A large watermark on the screen doesn’t work as well as a bunch of small ones.
  4. The space between the watermarks should be smaller to increase the coverage.
  5. There should be a function to prevent tampering.

List all the points above, and we’ll just implement them in turn.

The first point

Good implementation. We just create a DOM element and insert it into the body.

 const divObj = document.createElement('div');
    const styleStr = `
                  position:fixed;
                  top:0;
                  left:0;
                  bottom:0;
                  right:0;
                  z-index:999999;
                  background-repeat:repeat;
                  `;
    divObj.setAttribute('style', styleStr);
    document.body.appendChild(divObj);
Copy the code

The second point

The content of watermark is obtained from cookie.

const user = /user_name=([^;] +)/.exec(document.cookie); const name = Array.isArray(user) && user.length === 2 && user[1] ? User [1] : 'configured watermark ';Copy the code

The name here is the user information we got.

At four o ‘clock in the third

Combining the two, use name as a background image and repeat. We want to convert text to images, so canvas is a good choice. At the same time, we have to consider that the image is not too large (in order to meet the third point), so we will use the size of 200*100.

const canvasObj = document.createElement('canvas'); const canvas2d = canvasObj.getContext('2d'); canvasObj.width = 200; canvasObj.height = 100; canvas2d.font = fontSize + 'px Arial'; Canvas2d. FillStyle = 'rgba (128128128, 6); Canvas2d. Translate (canvasobj.width / 4, canvasobj.height / 2); canvas2d.rotate((-30 / 180) * Math.PI); canvas2d.fillText(name, 0, canvasObj.height / 2); // convert canvas toDataURL const base64Url = canvasobj.todataurl ('image/ PNG '); // convert canvas toDataURL const base64Url = canvasobj.todataurl ('image/ PNG ');Copy the code

Now we have a Base64 address that we can use as our image.

The first five

To have anti-tampering function, specifically reflected in the watermark we create can not easily let others to delete, secondly, the content of the watermark can not easily be changed, whether it is the content of the watermark or the color of the watermark style.

As for the watermarking content, we use the login information in the cookie. If someone changes the value in the cookie, the login information will be invalid and sso side will be forced to jump to the login page, so this can be assigned to the login system.

The DOM cannot be easily deleted or styled, so we need to use the MutationObserver API, which listens for changes in the DOM and triggers a callback. We can avoid this problem by re-executing the watermarking method in the callback.

if (MutationObserver) { let waterMarkOb = new MutationObserver(function () { const _globalWatermark = document.querySelector(`domId`); / / when the style or watermark element is dom node will be redrawn if change ((_globalWatermark && _globalWatermark. GetAttribute (' style ')! == styleStr) || ! _globalWatermark ) { waterMarkOb.disconnect(); waterMarkOb = null; setWaterMark(); }}); Watermarkob. observe(document.body, {attributes: true, subtree: true, childList: true,}); }Copy the code

The last point

One thing to note is that our watermark function should not affect the use of business as much as possible. So here we have to consider two things:

  1. Our dom watermark is at the top of the screen, level 99999, but don’t interfere with the elements below. So we need to increasepointer-events:noneProperty, does not affect mouse operations.
  2. If we want to implement watermarking without changing the front-end code, we need to start on the server. For example, in Nginx, we can use the sub_filter module to replace the returned text. For example,
 subs_filter "(<\/body>)" "$1<script src=\"https://cdn.xxx.com/watermark.js\"></script>" irg;
Copy the code

To this our watermark function is realized. Consistent principle, “BB is nothing, show me the code”. The overall code is as follows:

! Rotate: rotate (function () {const options = {id: 'globalWaterMark', fontSize: 10, color: 'rgba(128,128,128,.6)', rotate: '-30', userName: 'other identity'}; Const {fontSize, color, id} = options; / / function createWaterMark() {const {fontSize, color, id} = options; const user = /user_name=([^;] +)/.exec(document.cookie); const name = Array.isArray(user) && user.length === 2 && user[1] ? user[1] : options.userName; const canvasObj = document.createElement('canvas'); const canvas2d = canvasObj.getContext('2d'); canvasObj.width = 200; canvasObj.height = 100; canvas2d.font = fontSize + 'px Arial'; canvas2d.fillStyle = color; canvas2d.translate(canvasObj.width / 4, canvasObj.height / 2); canvas2d.rotate((-30 / 180) * Math.PI); canvas2d.fillText(name, 0, canvasObj.height / 2); // convert canvas toDataURL const base64Url = canvasobj.todataurl ('image/ PNG '); // convert canvas toDataURL const base64Url = canvasobj.todataurl ('image/ PNG '); return base64Url; } function setWaterMark() { const { fontSize, color, id } = options; const url = createWaterMark(); const target = document.getElementById(id); if(target){ document.body.removeChild(target) } const divObj = document.createElement('div'); divObj.id = options.id; const styleStr = ` position:fixed; top:0; left:0; bottom:0; right:0; z-index:999999; background-repeat:repeat; pointer-events:none; background-image:url('${url}')`; divObj.setAttribute('style', styleStr); document.body.appendChild(divObj); Window. / / to monitor the DOM changes const MutationObserver = MutationObserver | | window. WebKitMutationObserver; if (MutationObserver) { let waterMarkOb = new MutationObserver(function () { const _globalWatermark = document.querySelector(`#${id}`); / / when the style or watermark element is dom node will be redrawn if change ((_globalWatermark && _globalWatermark. GetAttribute (' style ')! == styleStr) || ! _globalWatermark ) { waterMarkOb.disconnect(); waterMarkOb = null; setWaterMark(); }}); Watermarkob. observe(document.body, {attributes: true, subtree: true, childList: true,}); } } document.addEventListener('DOMContentLoaded', function () { setWaterMark(); }); }) ();Copy the code