Watermark高阶组件
Watermark作为高阶组件,包裹编辑器内容,即代码中的children,并传入用户信息做水印,其中的核心方法createWatermark(),传入当前的dom,方便讲水印作为背景印到div上。
export default class Watermark extends React.PureComponent {
static propTypes = {
userInfo: propTypes.object,
children: propTypes.any,
getCurrentUserInfo: propTypes.func.isRequired,
isPrivate: propTypes.bool,
};
componentDidMount() {
if (this.props.userInfo) {
this.init();
} else {
this.props.getCurrentUserInfo();
}
}
componentDidUpdate(preProps) {
if (this.props.userInfo !== preProps.userInfo || this.props.isPrivate !== preProps.isPrivate) {
this.init();
}
}
init = () => {
const { userInfo, isPrivate } = this.props;
if (userInfo) {
const {
userVO: {
name,
// email,
id,
},
} = userInfo;
// console.log(`${name}(${id})`);
createWatermark(this.container.current, `${name}(${id})`, isPrivate);
}
};
render() {
const { children } = this.props;
return <div ref={this.container}>{children}</div>;
}
container = React.createRef();
}
添加水印核心方法
import { getByteLength } from '@sjk/fe-components-react';
import colorUtil from '@/utils/colorUtil';
// 给元素加水印
export default function(el, text, isPrivate) {
const pageBackgroundColor = window.getComputedStyle(document.getElementsByTagName('body')[0]).backgroundColor;
let backgroundColor = '#fff';
let color = '#fefefe';
const isDarkColorTheme = colorUtil.isDarkColor(pageBackgroundColor);
if (isDarkColorTheme) {
backgroundColor = pageBackgroundColor;
color = colorUtil.getFontColorFromDarkStyle(pageBackgroundColor);
}
const textLength = getByteLength(text);
let canvas = window.document.createElement('canvas');
const fontSize = 14;
// debugger;
const width = (fontSize * textLength) / 2 + 30;
const height = isPrivate ? 104 : fontSize;
canvas.width = isPrivate ? (width > 260 ? width : 260) : width;
canvas.height = height;
let ctx = canvas.getContext('2d');
ctx.font = `${fontSize}px sans-serif`;
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, width, height);
// 隐藏个人信息的颜色
ctx.fillStyle = color;
ctx.fillText(text, 30, fontSize);
if (isPrivate) {
ctx.fillText(text, 60, fontSize * 2);
ctx.fillText(text, 90, fontSize * 3);
ctx.fillText(text, 120, fontSize * 4);
ctx.rotate((35 * Math.PI) / 180);
ctx.font = `32px sans-serif`;
// 切换颜色显示警告信息
ctx.fillStyle = 'rgba(242, 242, 242, 0.603921568627451)';
if (isDarkColorTheme) {
ctx.fillStyle = 'rgba(80, 80, 80, 0.603921568627451)';
}
ctx.fillText('私密文档', 10, 20);
}
const img = canvas.toDataURL('image/png');
// debugger
el.style.background = `url("${img}") left top`;
el = null;
canvas = null;
ctx = null;
}
辅助函数
// 获取字符串字节长度,汉字两个字节,字母一个字节
export default function getByteLength(str) {
if (!str) return 0;
if (typeof str != 'string') {
str += '';
}
// eslint-disable-next-line
return str.replace(/[^\x00-\xff]/g, '01').length;
}
颜色深浅判断,从而显示字体颜色
export default {
regex: {
rgbStyleAll: /(^rgb\((\d+),\s*(\d+),\s*(\d+)\)$)|(^rgba\((\d+),\s*(\d+),\s*(\d+)(,\s*\d+\.\d+)*\)$)/,
hexStyle: /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/,
rgbaStyle: /^rgba\((\d+),\s*(\d+),\s*(\d+)(,\s*\d+\.\d+)*\)$/,
rgbStyle: /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/,
hexWidthStyle: /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,
},
isRgbStyle(rgb) {
return this.regex.rgbStyleAll.test(rgb);
},
isHexStyle(hex) {
this.regex.hexStyle.test(hex);
},
isDarkColor(colorStyle) {
if (this.isRgbStyle(colorStyle)) {
if (colorStyle.indexOf('rgba') >= 0) {
const rgba = this.regex.rgbaStyle.exec(colorStyle);
const r = parseInt(rgba[1]);
return r < 128;
} else {
const rgb = this.regex.rgbStyle.exec(colorStyle);
const r = parseInt(rgb[1]);
return r < 128;
}
} else if (this.isHexStyle(colorStyle)) {
const rgb = this.regex.hexWidthStyle.exec(colorStyle);
const r = parseInt(rgb[1], 16);
return r < 128;
} else {
return false;
}
},
/**
* 获取背景色和字体颜色
* @param colorStyle
*/
getFontColorFromDarkStyle(colorStyle) {
if (this.isRgbStyle(colorStyle)) {
if (colorStyle.indexOf('rgba') >= 0) {
const rgba = this.regex.rgbaStyle.exec(colorStyle);
return `rgba(${rgba[1] - 1}, ${rgba[2] - 1}, ${rgba[2] - 1}, ${rgba[4]})`;
} else {
const rgb = this.regex.rgbStyle.exec(colorStyle);
return `rgb(${rgb[1] - 1}, ${rgb[2] - 1}, ${rgb[2] - 1})`;
}
} else {
const rgb = this.regex.hexWidthStyle.exec(colorStyle);
const r = parseInt(rgb[1], 16);
const g = parseInt(rgb[2], 16);
const b = parseInt(rgb[3], 16);
return `rgb(${r}, ${g}, ${b})`;
}
},
};