Canvas
實現網頁水印的方案十分感興趣,因而對相關代碼加以修改,實現了一個 React
水印組件併發布到 👉 npm。Canvas
生成水印,並使用 MutationObserve
(能夠監聽DOM結構變化的接口)監視 DOM
的變更,使得水印不可被刪除、且屬性不可被修改。npm install --save watermark-component-for-react
複製代碼
import React from 'react';
import WaterMark from 'watermark-component-for-react';
import * as styles from './index.css';
class ReactDemo extends React.Component{
render () {
const content = `內部文檔,請勿外傳 by-前端小黑`;
return (
<WaterMark content={content}>
<div className={styles.wrapper}>hello world</div>
</WaterMark>
);
}
}
export default ReactDemo;
複製代碼
WaterMark
組件中,即做爲 WaterMark
的子組件。使用 MutationObserve
監視 DOM 的變更,水印不可被刪除、且屬性不可被修改: css
豐富的 props 使得水印組件可實現定製化需求:前端
成員 | 說明 | 類型 | 默認值 |
---|---|---|---|
style | watermark最外層組件內聯樣式 | undefined | object | undefined |
container | 容器 | HTMLDivElement | document.body |
width | canvas元素寬 | string | 300 |
height | canvas元素高 | string | 200 |
textAlign | 繪製文本的對齊方式 | string | left |
textBaseline | 文本基準線 | string | bottom |
font | 字體大小及樣式 | string | 16px Microsoft Yahei |
fillStyle | 自定義水印的顏色 | string | black |
content | 水印內容 | string | 內部文檔,請勿外傳 |
globalAlpha | 設置圖形和圖像透明度的值 | number | 0.1 |
rotate | 文字旋轉角度 | number | 16 |
zIndex | 元素堆疊順序 | number | 1000 |
import * as React from 'react';
import { watermark } from '../../utils/lib'
export default class WaterMark extends React.Component {
constructor(props) {
super(props);
this.container = null;
}
componentDidMount () {
const { style, ...options } = this.props;
watermark({
container: this.container,
...options,
});
}
render () {
const style = {
position: 'relative',
...this.props.style,
};
return (
<div ref={(el) => this.container = el} id="watermark" style={style}>
{this.props.children}
</div>
);
}
}
複製代碼
watermark
這個方法,具體代碼以下:export function watermark (options) {
const {
container = document.body, // 容器
width = '300', // canvas元素寬
height = '200', // canvas元素高
textAlign = 'left', // 文字對齊
textBaseline = 'bottom', // 基準線
font = '16px Microsoft Yahei', // 字體大小及樣式
fillStyle = '#000', // 自定義水印的顏色
content = '內部文檔,請勿外傳', // 水印內容
globalAlpha = 0.1, // 設置圖形和圖像透明度的值
rotate = 16, // 文字旋轉角度
zIndex = 1000, // 元素堆疊順序
} = options;
let canvas = document.createElement('canvas');
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
let ctx = canvas.getContext('2d'); // 獲取 canvas2d 上下文
ctx.globalAlpha = globalAlpha;
ctx.textAlign = textAlign;
ctx.textBaseline = textBaseline;
ctx.font = font;
ctx.fillStyle = fillStyle;
ctx.rotate((Math.PI * rotate) / 180);
ctx.fillText(content, 50, 50);
const base64Url = canvas.toDataURL(); // 返回一個包含圖片展現的 data URI
const __wm = document.querySelector('.__wm');//選擇器
const watermarkDiv = __wm || document.createElement("div");
const styleStr = `
position:absolute;
top:0px;
left:0px;
width:100%;
height:100%;
z-index:${zIndex};
pointer-events:none;
background-repeat:repeat;
background-image:url('${base64Url}')`;
watermarkDiv.setAttribute('style', styleStr);
watermarkDiv.classList.add('__wm'); // 爲元素添加「__wm」類名
container.style.position = 'relative';
if (!__wm) {
container.appendChild(watermarkDiv); // 添加元素
}
const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
// 檢查瀏覽器是否支持這個API
if (MutationObserver) {
const args = arguments[0];
let mo = new MutationObserver(function () {
const __wm = document.querySelector('.__wm');
// 只在__wm元素變更才從新調用
if ((__wm && __wm.getAttribute('style') !== styleStr) || !__wm || container.style.position !== 'relative') {
// 避免一直觸發
mo.disconnect();
mo = null;
watermark(args);
}
});
mo.observe(container, {
attributes: true, // 觀察目標節點的屬性節點
subtree: true, // 觀察目標節點的全部後代節點
childList: true, // 觀察目標節點的子節點
})
}
};
複製代碼
MutationObserve
,當水印組件被刪除、屬性被修改或水印組件的容器定位屬性 position
不爲 relative
時,會從新調用watermark
方法。MutationObserve
實現),當組件被刪除時動態插入新的水印。以上內容若有遺漏錯誤,歡迎留言 ✍️指出,一塊兒進步💪💪💪react
若是以爲本文對你有幫助,🏀🏀留下你寶貴的 👍npm