网页水印入门

5,509 阅读3分钟

前言

Coding 应当是一生的事业,而不仅仅是 30 岁的青春饭
本文已收录 GitHub https://github.com/ponkans/F2E,欢迎 Star,持续更新

网站浏览中,常常需要网页水印,来防止用户截图或者录屏暴露敏感信息后无法追踪用户来源。比如钉钉、飞书等软件,聊天背景会有你的花名。

水怪怪今天手把手带你实现一个自定义水印的 npm 包,并发布至 npm 仓库。

思路

  • 获取标记信息,比如用户名、用户 ID 等(也就是你想打上水印的目标对象)
  • 绘制水印,绘制工具我们可以采用 canvas

实现

创建一个 npm 项目
mkdir watermarkly && cd watermarkly
npm init
touch index.js
touch README.md
开放参数
  • fontSize:水印字体大小
  • color:水印字体颜色
  • id:Canvas ID
  • text:水印文案
  • size:水印大小
  • clarity:水印清晰度
创建画布

根据 id 生成 canvas 画布,如果没有 id 参数传入,则自动生成一个随机字符串,防止和页面其他 DOM ID 冲突,如果已经存在该 id 对应的画布,需要先清除再生成。

画布大小为可用屏幕大小。画布 fix 固定在可视窗口,z-index 为-1。

// 删除已有画布
let oldCanvas = document.getElementById(this.params.id);
if(oldCanvas){
    oldCanvas.parentNode.removeChild(oldCanvas);
}

// 创建画布
let body = document.getElementsByTagName('body');
let width = window.screen.width;
let height = window.screen.height;
let canvas = document.createElement('canvas');

let id = this.params.id
if(!id){
    id = randomString(18);
}

// 设置画布id
canvas.setAttribute('id'this.params.id); 
canvas.width = width * this.params.clarity;
canvas.height = height * this.params.clarity;
canvas.style.cssText'position: fixed;width: 100%;height: 100%;left:0;top:0;z-index: -1;';
body[0].appendChild(canvas);

填充画布

  • 计算 x 轴和 y 轴可展示水印个数,要做冗余计算,防止出现边界水印缺失

  • 画布逆时针旋转 15 度

  • 遍历 x,y 依次绘制水印

let canvas = document.getElementById(this.params.id);
let cxt = canvas.getContext('2d');

let redundance = 10;
let xCount = window.screen.width * this.params.clarity / this.params.size + redundance;
let yCount = window.screen.height * this.params.clarity / this.params.size + redundance;

cxt.rotate(-15*Math.PI/180);


for(let i = 0; i < xCount; i++) {
  for(let j = 0; j < yCount; j++) {
    cxt.fillStyle = this.params.color;
    cxt.font = this.params.fontSize + ' Arial';
    cxt.fillText(this.params.textthis.params.density*(i-redundance/2), j*this.params.size); 
  }
}

安全锁

怪怪我兴致勃勃的写好了组件给老大看,结果,被吐槽说不严谨!what ?发生了什么?

凶手原来……

有点 coding 经验的同学,很容易通过各种骚操作抹掉水印,比如打开调试窗口删除 canvas 或者修改 canvas 的样式属性。

所以我们还需要对水印加安全锁,提高安全等级。

  • 可以设置定时器,定时检查水印状态。
let self = this;
  window.setInterval(function(){
  let canvasDom = document.getElementById(self.params.id);            
  if (!canvasDom 
    || canvasDom.style.cssText !== 'position: fixed; width: 100%; height: 100%; left: 0px; top: 0px; z-index: -1;' 
    || canvasDom.width !== (window.screen.width * self.params.clarity)
    || canvasDom.height !==  (window.screen.height * self.params.clarity)) {
    self.init();
  }
}, 500);

发布

  • npm login
  • npm publish

水印效果

npm i --save watermarkly
import Watermark from 'watermarkly';
new Watermark({
    text'test'
});