/* * @Author: allen_ * @Date: 2024-05-22 10:45:18 * @Email: zhangxudong_a@aspirecn.com * @LastEditors: allen_ * @LastEditTime: 2024-05-23 15:43:17 * @Description: 水印 * @example: * watermark.set(this.$refs.body, { text: '水印文字', gap: [50, 100], fontSize: 14, color: 'rgba(0, 0, 0, 0.35)'}) */ import html2canvas from 'html2canvas' const watermark = {} /** * @description: 设置水印 * @param {*} sourceBody 需要设置的元素 * @param {*} text 水印文字 * @param {array} gap 水印间距 [上下间距, 左右间距] * @param {*} fontSize 水印文字大小 * @param {*} color 水印字体颜色 * @param {*} zIndex 水印层级 * @param {*} rotate 水印角度 */ const setWatermark = (sourceBody, { text = 'watermark', gap = [100, 120], fontSize = 14, color = 'rgba(0, 0, 0, 0.25)', zIndex = 9999, rotate = -22, custom = null }) => { // @Explain: 生成随机元素 id const id = Math.random() * 10000 + '-' + Math.random() * 10000 + '/' + Math.random() * 10000 if (document.getElementById(id) !== null) { document.body.removeChild(document.getElementById(id)) } let canvasData = null if (!custom) { const can = document.createElement('canvas') can.height = gap[0] // 水印上下间距 can.width = gap[1] // 水印左右间距 const cans = can.getContext('2d') cans.rotate((rotate * Math.PI) / 180) cans.font = fontSize + 'px Microsoft YaHei' cans.fillStyle = color cans.textAlign = 'left' cans.textBaseline = 'Middle' cans.fillText(text, can.width / 20, can.height / 3) canvasData = can.toDataURL('image/png', 1.0) } else { canvasData = custom } const water_div = document.createElement('div') water_div.id = id water_div.className = 'watermark-body' const styleStr = ` background: url(${canvasData}) left top repeat; pointer-events: none; width: 100%; height: 100%; position: absolute; z-index: ${zIndex}; top: 0px; left: 0px; ` water_div.setAttribute('style', styleStr) const partnerStyle = ` ${sourceBody.getAttribute('style') || ''} position: relative; userSelect: none; ` sourceBody.setAttribute('style', partnerStyle) sourceBody.appendChild(water_div) // 防止水印被删除 const observer = new MutationObserver(() => { const wmInstance = document.getElementById(id) if ((wmInstance && wmInstance.getAttribute('style') !== styleStr) || !wmInstance) { // 如果标签在,只修改了属性,重新赋值属性 if (wmInstance) { // 避免一直触发 -- 水印属性修改了 wmInstance.setAttribute('style', styleStr) } else { // observer.disconnect() sourceBody.appendChild(water_div) } } else if (sourceBody.getAttribute('style') !== partnerStyle) { // @Explain: 判断父元素样式是否存在更改 sourceBody.setAttribute('style', partnerStyle) } }) observer.observe(sourceBody, { attributes: true, subtree: true, childList: true }) return id } // @Explain: 为元素设置水印 watermark.set = (sourceBody, opi) => { const domArr = Array.from(document.getElementsByClassName('watermark-body')) for (let i = domArr.length; i--;) { const element = domArr[i] element.remove() } if ((!opi.text && !opi.custom) || !sourceBody) return null if (!(sourceBody instanceof HTMLElement)) { // @Condition: 判断传入的元素是否为dom元素 || VueComponent sourceBody = sourceBody.$el } const id = setWatermark(sourceBody, opi) return id } // @Explain: html2canvas 创建元素 base64 watermark.baseImg = (el, scale = window.devicePixelRatio < 3 ? window.devicePixelRatio : 2) => { return new Promise((resolve) => { html2canvas(el, { useCORS: true, // 【重要】开启跨域配置 scale, allowTaint: true, // 允许跨域图片 backgroundColor: null // 是否设置背景色透明 }).then((canvas) => { const imgData = canvas.toDataURL('img/jpg', 1.0) resolve(imgData) }) }) } // @Explain: 创建水印方法 watermark.create = (text = 'watermark', callback = null, cache = true) => { if (callback && typeof callback === 'function') { // @Condition: 自定义水印元素创建方法 return callback(text, watermark) } // @Explain: 判断缓存创建的水印元素是否存在 if (watermark.cacheEl && cache) { watermark.cacheEl.querySelector('.watermark-user-info').innerText = text return watermark.cacheEl } const div = document.createElement('div') div.style = ` width: 200px; height: 160px; display: flex; align-items: center;` const watermarkDiv = document.createElement('div') watermarkDiv.style = ` width: 210px; height: 48px; display: flex; justify-content: center; align-items: center; flex-wrap: wrap; transform-origin: center; transform: rotate(-35deg);` const img = document.createElement('img') img.style = 'width: 201px;' // if you need image, edit here // img.src = require('@/assets/img/watermark.png') const userInfo = document.createElement('div') userInfo.className = 'watermark-user-info' userInfo.style = ` font-size: 12px; color: rgba(38, 42, 48, 0.1); letter-spacing: 0; font-family: PingFangSC-Regular;` userInfo.innerText = text watermarkDiv.appendChild(img) watermarkDiv.appendChild(userInfo) div.appendChild(watermarkDiv) watermark.cacheEl = div // 缓存水印元素 return div } export default watermark