跳到主要内容

Div

2024年06月18日
柏拉文
越努力,越幸运

一、认识


二、思路


2.1 元素虚化

pointer-events CSS 属性指定在什么情况下 (如果有) 某个特定的图形元素可以成为鼠标事件的 target。当它的被设置为 none 的时候,能让元素实体虚化,虽然存在这个元素,但是该元素不会触发鼠标事件。

2.2 禁止选中

CSS 属性 user-select 控制用户能否选中文本。除了文本框内,它对被载入为 chrome 的内容没有影响。

三、实现


3.1 JS

function cssHelper(el, prototype) {
for (let i in prototype) {
el.style[i] = prototype[i];
}
}

function calculateWatermarkCount(params) {
const { waterWidth, waterHeight } = params || {};

const { clientWidth, clientHeight } =
document.documentElement || document.body;

const column = Math.ceil(clientWidth / waterWidth);
const rows = Math.ceil(clientHeight / waterHeight);

return column * rows;
}

function createWatermarkDiv(params) {
const { text } = params || {};

const div = document.createElement("div");
div.innerHTML = text;

cssHelper(div, {
position: "absolute",
top: `50px`,
left: `50px`,
fontSize: `16px`,
color: "#000",
lineHeight: 1.5,
opacity: 0.1,
transform: `rotate(-15deg)`,
transformOrigin: "0 0",
userSelect: "none",
whiteSpace: "nowrap",
overflow: "hidden",
});

return div;
}

function createWatermark(params) {
const { text = "水印文案", waterWidth, waterHeight } = params || {};
const waterWrapper = document.createElement("div");

cssHelper(waterWrapper, {
position: "fixed",
top: "0px",
right: "0px ",
bottom: "0px",
left: "0px",
overflow: "hidden",
display: "flex",
"flex-wrap": "wrap",
"pointer-events": "none",
});

const watermarkCount = calculateWatermarkCount({
waterWidth,
waterHeight,
});

for (let i = 0; i < watermarkCount; i++) {
const wrap = document.createElement("div");
cssHelper(
wrap,
Object.create({
position: "relative",
width: `${waterWidth}px`,
height: `${waterHeight}px`,
flex: `0 0 ${waterWidth}px`,
overflow: "hidden",
})
);
wrap.appendChild(createWatermarkDiv({ text }));
waterWrapper.appendChild(wrap);
}

document.body.appendChild(waterWrapper);
return waterWrapper;
}

function observeWatermark(params) {
const { waterWrapper } = params || {};
const config = { attributes: true, childList: true, subtree: true };

const callback = function (mutationsList) {
for (let mutation of mutationsList) {
switch(mutation.type){
case "attributes":
if(mutation.target === waterWrapper){
document.body.appendChild(waterWrapper);
return;
}
break;
case "childList":
mutation.removedNodes.forEach(function (item) {
if (item === waterWrapper) {
document.body.appendChild(waterWrapper);
return;
}
});
break;
}
}
};
const targetNode = document.body;
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
}

const waterWrapper = createWatermark({
text: "柏拉文水印",
waterWidth: 180,
waterHeight: 100,
});

observeWatermark({ waterWrapper });

3.2 HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>明水印</title>
<link href="index.css" rel="stylesheet" />
</head>
<body>
<div>
<h3>标题 h3</h3>
<img src="../../images/50060231-77d6-4dfb-8752-4723549626dd-1.png"/>
</div>
<script src="./index.js"></script>
</body>
</html>