前言
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.text, this.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'
});