实现代码
class WaterMark {
constructor(text = "", options = {}) {
const defaultStyles = {
transform: 'rotate(-15deg)',
position: 'absolute',
overflow: 'hidden',
zIndex: 9999999,
opacity: 0.2,
fontFamily: '微软雅黑',
color: 'black',
textAlign: 'center',
padding: '10px 10px',
whiteSpace: 'nowrap',
display: 'block',
};
let { left = 220, top = 80, fontSize = 16, id = "", styles = {} } = options
this.styles = { ...defaultStyles, ...styles };
this.text = text;
this.left = Number(left);
this.top = Number(top);
this.fontSize = Number(fontSize)
this.id = id;
this.createWatermark()
window.addEventListener('resize', this.handleResize);
}
createMaskDiv(left, top) {
const maskDiv = document.createElement('div');
maskDiv.id = 'water_mask_id_0';
let styles = { ...this.styles, left: `${left}px`, top: `${top}px`, fontSize: `${this.fontSize}px` }
for (var key in styles) {
maskDiv.style[key] = styles[key];
}
maskDiv.innerText = this.text;
return maskDiv;
}
createWatermark() {
let maskDiv = this.createMaskDiv(0, 0)
document.body.appendChild(maskDiv);
let width = maskDiv.offsetWidth
let height = maskDiv.offsetHeight
document.body.removeChild(maskDiv);
const div = document.createElement('div');
div.id = 'eb-watermark';
div.style.cssText = `pointer-events: none !important; display: block !important; visibility: visible !important; position: fixed !important; top: 0 !important; left: 0 !important; opacity: 1 !important; z-index: 0 !important; transform: translateX(0) !important;`;
const shadowRoot = div.attachShadow({ mode: 'open' });
let left = width + this.left
let top = height + this.top
for (let i = 0; i < window.innerWidth; i += left) {
for (let j = 0; j < window.innerHeight; j += top) {
shadowRoot.appendChild(this.createMaskDiv(i, j));
}
}
const observerConfig = { childList: true, subtree: true, attributes: true, attributeFilter: ['id', 'style'] };
const observer = new MutationObserver(this.handleMutation.bind(this));
observer.observe(document.body, observerConfig);
const shadowRootObserver = new MutationObserver((mutations) => this.handleShadowRootMutation(mutations, shadowRoot).bind(this));
shadowRootObserver.observe(shadowRoot, { ...observerConfig, characterData: true });
document.body.appendChild(div);
}
handleMutation(mutations) {
mutations.forEach((mutation) => {
const watermark = document.getElementById('eb-watermark');
if (mutation.removedNodes.length > 0 || mutation.target.id === 'eb-watermark') {
if (!watermark) {
this.createWatermark();
}
}
if (mutation.type === 'attributes' && (mutation.target.id === 'eb-watermark' || mutation.attributeName === 'style')) {
if (watermark) {
watermark.remove();
}
this.createWatermark();
}
});
const watermark = document.body.querySelector('#eb-watermark');
if (!watermark || watermark.parentElement !== document.body || !watermark.shadowRoot || !watermark.shadowRoot.querySelector('#water_mask_id_0')) {
if (watermark) {
watermark.remove();
}
this.createWatermark();
}
}
handleShadowRootMutation(mutations, shadowRoot) {
mutations.forEach((mutation) => {
if (mutation.removedNodes.length > 0 || mutation.type === 'attributes' || (mutation.type === 'characterData' && (mutation.target.parentNode === shadowRoot || mutation.target.parentNode.parentNode === shadowRoot))) {
const watermark = document.getElementById('eb-watermark');
if (watermark) {
watermark.remove();
}
this.createWatermark();
}
});
}
handleResize() {
const watermark = document.getElementById('eb-watermark');
if (watermark) {
watermark.remove();
}
this.createWatermark();
}
}
export default WaterMark;
使用
import WaterMark from './watermark';
new WaterMark('我是水印啊');
待优化
- 目前只支持插入到body的全屏水印,下一步优化支持指定id的div水印