preface

In Web projects, in order to protect intellectual property rights, or background systems to quickly locate individuals, the existence of page watermarking is very necessary. Here is a simple way to add a page watermark to the front end.

Technical analysis

In terms of effect, the desired effect is to overlay the watermark information on the box that needs to load the watermark. The first solution that comes to mind is to add a new box filled with elements that you want to watermark. Then set the watermark to the background image. However, I realized that if many elements on a page wanted to be watermarked separately, this would require too much work and would insert a lot of unnecessary DOM. So use :after pseudo-element instead. Once you’ve defined the pseudo-element, you just need to add a class name to the DOM where you want to add the watermark. However, the first thing the two schemes need to achieve is to generate images from text.

Implementation scheme

1. Generate a background image

To realize the image of the custom text content, you can generate a custom text canvas through canvas, and then call Canvas.todataURL () to generate base64 string, as the background of the element; The implementation code is as follows

// Configure the type definition
type imgOptions = {
  / / width
  width: number;
  / / height
  height: number;
  // Watermark the content
  content: string;
  // Watermark font
  font: string;
  // Watermark color
  color: string;
  // Deflection Angle (deg)
  rotateDegree: number;
  // The X offset
  x: number;
  // The Y offset
  y: number;
};

function createImgBase(options: imgOptions) :string {
  const canvas = document.createElement('canvas');
  const text = options.content;
  // To create a text interleaved effect, create a double width image
  canvas.width = options.width * 2;
  canvas.height = options.height;
  const ctx = canvas.getContext('2d');
  if (ctx) {
    // X-axis shadow distance, negative value means up, positive value means down
    ctx.shadowOffsetX = 2;
    // Y-axis shadow distance, negative value indicates left, positive value indicates right
    ctx.shadowOffsetY = 2;
    // The opacity of the shadow
    ctx.shadowBlur = 2;
    ctx.font = options.font;
    ctx.fillStyle = options.color;
    ctx.rotate(options.rotateDegree);
    ctx.textAlign = 'left';
    ctx.fillText(text, options.x, options.y);
  }
  return canvas.toDataURL('image/png');
}
Copy the code

2. Add the background image to the pseudo element

According to the technical analysis scheme, the generated IMG can be set as the background image of a class ::after pseudo-element. In this way, the element can be watermarked by adding a custom class name to the DOM to which you want to add a watermark

// Configuration type
type watermarkOptions = {
  // Define the class nameclassName? :string;
  / / widthwidth? :number;
  / / heightheight? :number;
  // Copy contentcontent? :string;
  / / fontfont? :string;
  / / colorcolor? :string;
  // Deflection Anglerotate? :number;
  // Location modeposition? :string;
  // Top distancetop? :number;
  // Left distanceleft? :number;
  / / hierarchyzIndex? :number;
};

/** * Generate watermark *@param {String} ClassName indicates the watermark className *@param {Number} Width the width *@param {Number} * height height@param {String} The content content *@param {String} The font font *@param {String} Color Custom styles: such as font color (using RGBA) *@param {Number} Rotate Rotate Angle *@param {String} Position Indicates the watermark positioning mode *@param {Number} Top Position * from the top@param {Number} Left Distance from left *@param {Number} ZIndex watermark level */
function genWaterMark({
  className = 'watermarked',
  width = 340,
  height = 240,
  content = 'watermark',
  font = '14px PingFang SC, sans-serif',
  color = 'rgba (156, 162, 169, 0.3)',
  rotate = -14,
  position = 'absolute',
  top = 0,
  left = 0,
  zIndex = 1000,
}: watermarkOptions) :void {
  const option = {
    width,
    height,
    content,
    font,
    color,
    rotateDegree: (rotate * Math.PI) / 180};// To achieve the effect of interleaving watermarks, two watermarks in different positions are generated here to fix relative positions
  constdataUri1 = createImgBase({ ... option,x: 100.y: 140});constdataUri2 = createImgBase({ ... option,x: 400.y: 340});let defaultStyle = document.createElement('style');
  defaultStyle.innerHTML = `.${className}:after {
    content: '';
    display: block;
    width: 100%;
    height: 100%;
    ${top || top === 0 ? `top: ${top}px; ` : ' '}
    ${left || left === 0 ? `left: ${left}px; ` : ' '}background-repeat: repeat; pointer-events: none; } `;

  let styleEl = document.createElement('style');
  styleEl.innerHTML = `.${className}:after
  {
    ${position ? `position: ${position}` : ' '};
    ${zIndex ? `z-index:${zIndex}` : ' '};
    background-image: url(${dataUri1}), url(${dataUri2});
    background-size: ${option.width * 2}px ${option.height}px; } `;
  document.head.appendChild(defaultStyle);
  document.head.appendChild(styleEl);
}


Copy the code

3. Invoke methods

  • Create a new HTML page and import JS
<style>
    body {
      margin: 0; {} *box-sizing: border-box;
    }
    .main {
      height: 100vh;
      width: 100vw;
      padding: 15px;
      display: flex;
      justify-content: space-between;
    }

    .main .left..main .right {
      position: relative;
      height: 100%;
      width: 49%;
      border: 1px solid #66ccff;
    }
</style>
<body>
    <script src="./water-mark.js"></script>
    <div class="main">
        <div class="left"></div>
        <div class="right"></div>
    </div>
</body>
Copy the code

Results the following

  • A method is called
const option = {
    content: 'Test watermark'.className: 'watermarked'}; genWaterMark(option);Copy the code
  • First of all to.leftAdd a class name to test the effect
  <div class="main">
    <div class="left watermarked">
    </div>
    <div class="right"></div>
  </div>
Copy the code

  • Let’s look at the simultaneous.rightAdd a watermark effect
  <div class="main">
    <div class="left watermarked">
    </div>
    <div class="right watermarked"></div>
  </div>
Copy the code

conclusion

At this point, the front-end generating and adding watermark scheme is basically completed. However, the security of this scheme is very fragile, a little bit of front-end knowledge of the people know that you can modify the CSS through the console to hide the watermark, so that there is no protection effect. Therefore, you need to design a scheme that prevents users from hiding or removing watermarks through the console. Watermarking anti-delete solution