前端如何優雅的新增水印及去除水印

林恒發表於2024-07-03

🧑‍💻 寫在開頭

點贊 + 收藏 === 學會🤣🤣🤣

在最近接手的一個專案中,需要對整個頁面加上一個水印,還需要動態修改增加背景色功能。由於使用的第三方庫不支援背景色功能,故記錄一下。文末會附上如何利用技術手段去除水印

第三方庫:watermark-plus

主要使用步驟

npm i watermark-plus
import WaterMark from 'watermark-plus'
const waterMark = new WaterMark({
  content: '水印內容',
  width: 200,
  height: 100,
  alpha: 0.2,
  background: 'yellow', // 當前這個引數不支援,需要改原始碼
  bAlpha: background == '#ffffff' ? '0' : 0.18,
})

為什麼背景色要在水印上加,而不在其他元素上加?

主要是隨著專案體系的增加以及瀏覽器的渲染分層,會導致有些地方的背景色被別的元素遮蓋。就算最後加上了,以後寫css也要格外小心,防止有z-index衝突

下面說一下怎麼實現增加背景色功能

先說一下watermark-plus庫實現水印的原理,只有瞭解其中的原理才能對症下藥

  1. 使用canvas把使用者傳入的內容繪製出來
  2. 使用toDataURL將Canvas影像轉換對應的data URI(base64)
  3. 動態建立兩個div元素,設定相對應的css屬性
  4. 監聽body下的dom元素變化(MutationObserver),如果修改或被移除的Nodes第一個元素是當前水印元素時會重新生成水印

背景色實現

  1. 在建構函式中處理background引數
  2. 使用canvas的fillStyle和fillRect增加背景色功能
  3. (o.fillStyle = t.background), o.fillRect(0, 0, t.width, t.height),
  4. 本人是基於打包後原始碼修改,所以程式碼看起來可能有點怪

最終背景色能夠成功展示

如何去除基於watermark-plus庫生成的水印

因為該庫監聽的body的dom變動,所以單純的去利用css去隱藏水印是行不通的,它會重新生成水印元素

可以利用原始碼中的邏輯判斷繞過重新生成邏輯

只需要讓removedNodes的第一個元素不是水印元素就可以了

以下是實現去除水印的測試程式碼(水印元素預設被body元素appendChild)

const body = document.body
const children = body.childNodes
const fragment = document.createElement('createDocumentFragment')
// 最後一個是水印元素,不需要appendChild處理; appendChild如果是文件樹中已存在的,則會將原dom刪除,所以這塊不需要i++,children.length是個動態值
for (let i = 0; i < children.length - 2;) {
  fragment.appendChild(children[i])
}
body.innerHTML = ''
body.appendChild(fragment)
最終斷點呈現的效果

第一個不再是水印元素,所以可以繞過重新生成水印元素的邏輯,想要修復也很簡單,直接遍歷MutationRecord list判斷就行了

其餘去除水印的方法

1、其實也可以禁用javascript來達到去掉水印效果,只不過現代網頁如果離開了javascript就會喪失一些互動效果

2、利用瀏覽器的Overrides直接改寫邏輯,這對打斷點技術要求有點高,也可以嘗試一下。

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文件,大家一起討論學習,一起進步。

前端如何優雅的新增水印及去除水印

相關文章