在系統開發過程中,一些資料或頁面比較敏感的地方,客戶會要求實現水印效果,防止內部人員截圖或拍照洩露資訊。
自定義文字水印顧名思義就是利用js
在完成頁面渲染的同時,往頁面的最底層動態生成多個帶水印資訊的div
。
效果圖如下:
這個解決方案在使用過程中不僅可以自定義水印內容,還可以自定義樣式,如傾斜角angle
、透明度opacity
、字型fontFamily
、字型大小fontsize
、左右上下間隔等等。
其html內容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>水印輸出</title>
</head>
<body>
<div>
<h6>HELLO WORLD</h6>
<!-- 省略部分程式碼 -->
</div>
<!-- 引入js(路徑根據專案情況確定) -->
<script type="text/javascript" src="watermark.js"></script>
<script>
// 自定義樣式
const setting = {
"text": "測試水印", // 水印內容
"innerDate": true, // 在水印下方增加日期
"width": 110 // 水印寬度
};
// 渲染
watermark.build(setting);
</script>
</body>
</html>
自定義屬性如下:
const setting = {
text: "廣州XX公司授權", // 預設水印內容
beginX: 50, // 預設起始x座標
endX: 0, // 預設結束x座標
beginY: 50, // 預設起始y座標
endY: 0, // 預設結束y座標
intervalX: 150, // 預設橫向間隔寬度
intervalY: 100, // 預設縱向間隔高度
opacity: 0.3, // 字型透明度
angle: 20, // 字型傾斜度
fontsize: '15px', // 字型大小
fontFamily: '微軟雅黑', // 字型
width: 100, // 水印(每個)寬度
height: 80, // 水印(每個)高度
innerDate: false, // 是否附帶日期
};
完整js如下:
/**
* 自定義文字水印
*/
const watermark = function () {
return {
build: function(arg) {
// 獲取頁面寬度
let maxWidth = Math.max(document.body.scrollWidth, window.screen.width) - 20;
// 獲取頁面高度
let maxHeight = Math.max(document.body.scrollHeight, document.body.clientHeight) + 100;
if (maxHeight === 0){
console.info("該頁面無敏感內容~");
return;
}
const setting = {
text: "廣州XX公司授權", // 預設水印內容
beginX: 50, // 預設起始x座標
endX: 0, // 預設結束x座標
beginY: 50, // 預設起始y座標
endY: 0, // 預設結束y座標
intervalX: 150, // 預設橫向間隔寬度
intervalY: 100, // 預設縱向間隔高度
opacity: 0.3, // 字型透明度
angle: 20, // 字型傾斜度
fontsize: '15px', // 字型大小
fontFamily: '微軟雅黑', // 字型
width: 100, // 水印(每個)寬度
height: 80, // 水印(每個)高度
innerDate: false, // 是否附帶日期
};
// 預設變數與自定義變數結合
if (arguments.length ===1 && typeof arguments[0] === "object"){
const src = arguments[0] || {};
for (const key in src){
if (!src.hasOwnProperty(key) || !src[key]){
continue;
}
for (const def in setting){
if (key === def){
setting[def] = src[key];
}
}
}
}
// 計算列個數
const cols = parseInt((setting.intervalX + maxWidth - setting.beginX - setting.endX) / (setting.width + setting.intervalX) + "");
// 計算行個數
const rows = parseInt((setting.intervalY + maxHeight - setting.beginY - setting.endY) / (setting.height + setting.intervalY) + "");
// 水印內容附加日期
if (setting.innerDate){
const date = new Date();
setting.text = [setting.text, "<br>", date.getFullYear(), "年", date.getMonth() + 1, "月", date.getDate(), "日"].join("");
}
const fragment = document.createDocumentFragment();
let x, y;
for (let i=0; i<rows; i++){
y = setting.beginY + (setting.intervalY + setting.height) * i;
for (let j=0; j<cols; j++){
x = setting.beginX + (setting.width + setting.intervalX) * j;
const element = document.createElement('div');
element.id = 'watermark' + i + j;
// 設定傾斜角
element.style.MozTransform = "rotate(-" + setting.angle + "deg)";
element.style.msTransform = "rotate(-" + setting.angle + "deg)";
element.style.OTransform = "rotate(-" + setting.angle + "deg)";
element.style.transform = "rotate(-" + setting.angle + "deg)";
element.style.position = "absolute";
element.style.left = x + 'px';
element.style.top = y + 'px';
element.style.overflow = "hidden";
element.style.zIndex = "9999";
element.style.pointerEvents = 'none';
element.style.opacity = setting.opacity;
element.style.fontSize = setting.fontsize;
element.style.fontFamily = setting.fontFamily;
element.style.color = '#aaa';
element.style.textAlign = "center";
element.style.width = setting.width + 'px';
element.style.height = setting.height + 'px';
element.style.display = "block";
element.innerHTML = setting.text;
fragment.appendChild(element);
}
}
document.body.appendChild(fragment);
}
}
}();
- 其中獲取頁面寬度去的是螢幕的解析度
window.screen.width
考慮的是,當使用者通過F12
開啟開發者工具並顯示在左右兩邊時,此時重新整理頁面,通過document.body.clientHeight
獲取到的寬度是不包括開發者工具頁面的寬度的,這時候水印就沒有全部頁面佔滿,那麼使用者關閉開發者工具時,並不會重新整理頁面重新生成水印,所以就會出現一邊有水印而一遍沒有,如此水印便失去了震懾能力,所以應該去螢幕解析度較好。 - 列的個數及行的個數是根據自定義或者預設的水印起始結束座標、水印間隔寬高度、水印寬高度與頁面的寬高度進行動態計算,也就是說我們可以通過印起始結束座標、水印間隔寬高度、水印寬高度來控制水印的密集程度。
- 此外,通過靈活設定起始座標以及結束座標可以設定僅僅在頁面中的一小塊區域出現水印,其他區域則不出現水印。
- 函式的入參是一個
json
物件