/**
|
* @Description: canvas 简单的水印工具
|
* @Author: CcSimple
|
* @Github: https://github.com/CcSimple
|
*/
|
|
/**
|
* @Description: 时间格式化
|
* @param date
|
* @param format
|
* @returns {string|null}
|
*/
|
function timeFormat(date, format = 'YYYY-MM-DD') {
|
if (!date) return null;
|
if (typeof date === 'number') {
|
date = new Date(date);
|
}
|
const year = date.getFullYear();
|
const month = date.getMonth();
|
const day = date.getDate();
|
const hours24 = date.getHours();
|
const hours = hours24 % 12 === 0 ? 12 : hours24 % 12;
|
const minutes = date.getMinutes();
|
const seconds = date.getSeconds();
|
const dd = t => `0${t}`.slice(-2);
|
const map = {
|
YYYY: year,
|
MM: dd(month + 1),
|
MMMM: `${month + 1}月`,
|
M: month + 1,
|
DD: dd(day),
|
D: day,
|
HH: dd(hours24),
|
H: hours24,
|
hh: dd(hours),
|
h: hours,
|
mm: dd(minutes),
|
m: minutes,
|
ss: dd(seconds),
|
s: seconds
|
};
|
return format.replace(/Y+|M+|D+|H+|h+|m+|s+|S+|Q/g, str => String(map[str]));
|
}
|
|
// 水印参数
|
const defaultOption = {
|
id: 'watermark', // 水印id
|
watch: false,
|
content: 'vue-plugin-hiprint', // 水印内容
|
container: '.hiprint-printPaper', // 水印容器
|
width: 200, // 水印宽度
|
height: 200, // 水印高度
|
textAlign: 'center', // 水印文字水平对齐方式
|
textBaseline: 'middle', // 水印文字垂直对齐方式
|
fontSize: '14px', // 水印文字大小
|
fontFamily: 'Microsoft Yahei', // 水印文字字体
|
fillStyle: 'rgba(184, 184, 184, 0.3)', // 水印文字颜色
|
rotate: 25,// 水印文字旋转角度
|
timestamp: false, // 是否显示时间戳
|
format: 'YYYY-MM-DD HH:mm', // 时间戳格式
|
zIndex: 0
|
};
|
|
// 监听器
|
let observerMap = {};
|
|
/**
|
* @Description: 创建水印
|
* @param param
|
* @private
|
*/
|
function _createWatermark(param) {
|
const {
|
id,
|
watch,
|
content,
|
container,
|
width,
|
height,
|
textAlign,
|
textBaseline,
|
fontSize,
|
fontFamily,
|
fillStyle,
|
rotate,
|
timestamp,
|
format,
|
zIndex
|
} = param;
|
|
observerMap[id] = {
|
wmMo: null, // MutationObserver
|
wmTimer: null // timestamp
|
}
|
|
const canvas = document.createElement('canvas');
|
canvas.setAttribute('width', `${width}px`);
|
canvas.setAttribute('height', `${height}px`);
|
|
let containerDom = typeof container === 'string' ? document.querySelector(container) : container;
|
|
const ctx = canvas.getContext('2d');
|
ctx.textAlign = textAlign;
|
ctx.textBaseline = textBaseline;
|
ctx.font = `${fontSize} ${fontFamily}`;
|
ctx.fillStyle = fillStyle;
|
ctx.translate(width / 2, height / 2);
|
ctx.rotate(-(Math.PI / 180) * rotate);
|
ctx.fillText(`${content}`, 0, 0);
|
timestamp && ctx.fillText(`${timeFormat(new Date(), format)}`, 0, parseInt(fontSize) + 5);
|
|
let __vm = containerDom.querySelector('.__vm__' + id);
|
const watermarkDiv = __vm || document.createElement('div');
|
const withHeightStr = containerDom.getAttribute('style');
|
const styleStr = `position:absolute;user-select:none;top:0;left:0;${withHeightStr};z-index:${zIndex};pointer-events:none !important;background-repeat:repeat;background-image:url('${canvas.toDataURL()}');-webkit-print-color-adjust: exact;`;
|
|
watermarkDiv.setAttribute('style', styleStr);
|
watermarkDiv.classList.add('__vm__' + id);
|
|
if (!__vm) {
|
containerDom.insertBefore(watermarkDiv, containerDom.firstChild);
|
}
|
|
if (watch) {
|
const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
|
if (MutationObserver) {
|
observerMap[id]["wmMo"] = new MutationObserver((e) => {
|
let change = e.some(item => item.target.className == containerDom.className && item.type == 'attributes');
|
__vm = containerDom.querySelector('.__vm__' + id);
|
if ((__vm && __vm.getAttribute('style') !== styleStr) || !__vm || change) {
|
// 避免一直触发
|
observerMap[id]["wmMo"].disconnect();
|
observerMap[id]["wmMo"] = null;
|
delete observerMap[id]["wmMo"];
|
_createWatermark(param);
|
}
|
});
|
observerMap[id]["wmMo"].observe(containerDom, {
|
attributes: true, subtree: true, childList: true
|
});
|
}
|
}
|
|
if (format) {
|
let timeout = 1000 * 60 * 60 * 24;
|
if (format.includes('s')) {
|
timeout = 1000;
|
} else if (format.includes('m')) {
|
timeout = 1000 * 60;
|
} else if (format.includes('h') || format.includes('H')) {
|
timeout = 1000 * 60 * 60;
|
}
|
|
observerMap[id]["wmTimer"] = window.setTimeout(() => {
|
// 触发 MutationObserver
|
watermarkDiv.style.bottom = '0';
|
}, timeout);
|
}
|
}
|
|
/**
|
* @Description: 销毁水印
|
*/
|
const destroyWatermark = function (options) {
|
const {
|
id,
|
watch,
|
container,
|
} = options;
|
if (watch) {
|
let containerDom = typeof container === 'string' ? document.querySelector(container) : container;
|
// 监听器关闭
|
if (observerMap[id]) {
|
observerMap[id]["wmMo"] && observerMap[id]["wmMo"].disconnect();
|
observerMap[id]["wmMo"] = null;
|
observerMap[id]["wmTimer"] && window.clearTimeout(observerMap[id]["wmTimer"]);
|
observerMap[id]["wmTimer"] = null;
|
delete observerMap[id];
|
}
|
// 删除水印元素
|
const __vm = containerDom.querySelector('.__vm__' + id);
|
__vm && __vm.parentNode.removeChild(__vm);
|
}
|
}
|
|
/**
|
* @Description: 创建水印
|
* @param option
|
*/
|
const createWatermark = function (option) {
|
let options = Object.assign({}, defaultOption, option);
|
destroyWatermark(options);
|
_createWatermark(options);
|
}
|
|
// 暴露接口
|
export default {
|
createWatermark, destroyWatermark
|
}
|