watermark utils

PHOTO EMBED

Mon May 27 2024 01:25:59 GMT+0000 (Coordinated Universal Time)

Saved by @allen_ #javascript

/*
 * @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
content_copyCOPY

create watermark for you project.