《大前端 基礎元件》系列 80行實現一個網頁水印npm包

接水怪發表於2020-04-03

前言

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'
});
複製程式碼

總結

本文已收錄 GitHub https://github.com/ponkans/F2E,歡迎 Star,持續更新

很常見的一個小需求,抽下班時間簡單寫了下,主要也是因為前幾天看到技術交流群裡面一個小夥伴問了下,就順帶實現跟大家分享一把。

喜歡的小夥伴麻煩加個關注,點個在看哦,biubiubiu~

近期熱門原創推薦:


公眾號後臺回覆【水印】,可獲取原始碼。

微信搜尋【接水怪】或掃描下面二維碼回覆”加群“,我會拉你進技術交流群。講真的,在這個群,哪怕您不說話,光看聊天記錄也是一種成長。(阿里技術專家、敖丙作者、Java3y、蘑菇街資深前端、螞蟻金服安全專家、各路大牛都在)。

接水怪也會定期原創,定期跟小夥伴進行經驗交流或幫忙看簡歷。加關注,不迷路,有機會一起跑個步? ↓↓↓

相關文章