在系統開發過程中,一些數據或頁面比較敏感的地方,客戶會要求實現水印效果,防止內部人員截圖或拍照泄露信息。
自定義文字水印顧名思義就是利用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
對象