vue2 水印指令

519 阅读1分钟

/** 水印指令

  • 要求父元素position至少是relative、 fixed、 absolute其中一种
  • binding中可选的参数:和canvasWM中保持一致 / export default { /* 更新时 */ update(el: any, binding: any): void { // 获取绑定的参数 const { value }: any = binding; if (value) { if (typeof value === 'object') { if (typeof value.show === 'undefined' || value.show) { canvasWM({ container: el, ...value }); } else { canvasWM({ container: el, ...value, clear: true }); } } } else { canvasWM(); } } };

// 保存每个指令的observer const wmMutationObserverMap = new Map(); // 保存内容 const wmContentMap = new Map(); // 保存每个指令的是否显示参数 const paramsMap = new Map();

/** 生成图片

  • container:生成元素的对象

  • show:是否显示

  • clear:是否清除元素 */ function canvasWM({ container = document.body, width = '300px', height = '300px', font = '24px Microsoft Yahei', fillStyle = 'rgba(220, 220, 220, 0.3)', content = '', rotate = -30, show = true, clear = false }: any = {}): any { let id = container.id; if (!id) { id = wm_${new Date().getTime()}; container.setAttribute('id', id); }

    paramsMap.set(id, show); wmContentMap.set(id, content); // 监听元素变化,防止生成重复的监听器 let observer: any = wmMutationObserverMap.get(id); let styleStr: any = null; // 删除元素 if (clear) { clearWM(container);

     return;
    

    }

    /** 生成水印 */ // eslint-disable-next-line func-names, require-jsdoc const createWM = function (): void { // 生成canvas元素 const canvas: HTMLCanvasElement = document.createElement('canvas'); canvas.setAttribute('width', width); canvas.setAttribute('height', height); // 获取画板上下文 const ctx: any = canvas.getContext('2d'); ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.font = font; ctx.fillStyle = fillStyle; // 旋转 ctx.rotate((rotate * Math.PI) / 180); content = content || wmContentMap.get(id); ctx.fillText(content, 20, parseFloat(height));

     const base64Url = canvas.toDataURL();
     const wm = container.querySelector('.watermarker');
    
     const watermarkDiv = wm || document.createElement('div');
     styleStr = `
     position:absolute;
     top:0;
     left:0;
     bottom:0;
     right:0;
     width:100%;
     height:100%;
     color:rgba(0,0,0,.75);
     z-index:2000;
     pointer-events:none;
     background-repeat:repeat;
     background-image:url('${base64Url}')`;
    
     watermarkDiv.setAttribute('style', styleStr);
     watermarkDiv.classList.add('watermarker');
    
     if (!wm) {
     	container.insertBefore(watermarkDiv, container.firstChild);
     }
    

    };

    // 此方法是防止用户通过 修改样式或直接删除 if (!observer) { observer = new MutationObserver((mutationList: any) => { const showWM = paramsMap.get(id); const wmInstance = container.querySelector('.watermarker'); // 获取到你的水印dom // 防止被删除 if (!wmInstance && showWM) { console.log('水印被删除了!!!'); createWM(); // 防止下面的样式事件触发

     		return;
     	}
    
     	// 防止样式被改
     	if (wmInstance?.getAttribute('style') !== styleStr && showWM) {
     		console.log('改水印样式了!!!');
     		createWM();
    
     		return;
     	}
    
     	// // 防止类被改
     	// if (mutationList?.[0].attributeName === 'class' && showWM) {
     	// 	console.log(mutationList);
     	// 	console.log('改水印样式类了!!!');
     	// 	clearWM(container);
     	// 	createWM();
     	// }
     });
     observer.observe(container, {
     	childList: true, // 观察目标子节点的变化,是否有添加或者删除
     	attributes: true, // 观察属性变动
     	subtree: true // 观察后代节点,默认为 false
     });
     wmMutationObserverMap.set(id, observer);
    

    }

    /** 清除水印 */ function clearWM(el: HTMLElement): void { const wms = el.querySelectorAll('.watermarker'); wms.forEach((wm) => wm.remove()); }

    createWM(); }