Watermark 水印组件

前言

Watermark 组件

export const Watermark = ({ text = '', mountElement = '', color }) => { const _text = text // 动态生成 className const nameGenerator = () => { let className = '' const length = 2 + Math.ceil(Math.random() * 7) const dict = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'g', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' ] for (let i = 0; i < length; i++) { className += dict[Math.ceil(Math.random() * 26 - 1)] || 'a' } return className } const elementAttributeName = nameGenerator() // 生成水印的样式 const handleAddWaterMark = (str, element) => { const rotate = -25 const fontWeight = 'normal' const fontSize = '14px' const fontFamily = 'SimHei' const fontColor = color const rect = { width: 370, height: 300, left: 10, top: 150 } const can = document.createElement('canvas') can.className = 'mark-canvas' const watermarkDiv = element watermarkDiv.appendChild(can) can.width = rect.width can.height = rect.height can.style.display = 'none' can.style.zIndex = '999' const can2D = can.getContext('2d') can2D.rotate((rotate * Math.PI) / 180) can2D.font = ${fontWeight} ${fontSize} ${fontFamily} can2D.fillStyle = fontColor can2D.textAlign = 'center' can2D.textBaseline = 'middle' can2D.fillText(str, rect.left, rect.top) // 使用 canvas 生成图片 const styleStr = z-index: 9; position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; background-repeat: repeat; background-position: 0px 0px; background-image: url(${can.toDataURL('image/png')}); visibility: visible !important; watermarkDiv.setAttribute('style', styleStr) // 生成之后删除多余的 canvas 元素 const canvasDom = document.querySelector('.mark-canvas') if (canvasDom) { canvasDom.parentElement.removeChild(canvasDom) } } // 监听删除水印 const containObserver = () => { const bodyObserver = new MutationObserver((mutationList) => { mutationList.forEach((mutation) => { if (mutation.removedNodes.length > 0) { mutation.removedNodes.forEach((_target) => { if (_target.className === elementAttributeName) { createWaterDom(document.querySelector(#${mountElement})) } }) } }) }) bodyObserver.observe(document.querySelector(#${mountElement}), { childList: true }) return bodyObserver } // 生成水印 const createWaterDom = (element, containMutationObserver) => { let dom = document.createElement('div') dom.className = elementAttributeName element.appendChild(dom) handleAddWaterMark(_text, document.querySelector(.${elementAttributeName})) // 监听随机生成的类名 if (containMutationObserver) { let classNameObserver = new MutationObserver((mutationList) => { mutationList.forEach((mutation) => { if (mutation.type === 'attributes' && containMutationObserver !== null) { containMutationObserver.disconnect() dom.parentElement && dom.parentElement.removeChild(dom) createWaterDom(document.querySelector(#${mountElement})) containMutationObserver.observe(document.querySelector(#${mountElement}), { childList: true }) } }) }) classNameObserver.observe(dom, { attributes: true, childList: true }) } } React.useEffect(() => { const containMutationObserver = containObserver() createWaterDom(document.querySelector(#${mountElement}), containMutationObserver) }, [mountElement]) }

export const WatermarkComp = () => { return ( ) }