js生成水印

js生成水印

一. 使用

import Watermark from '@/utils/watermark'
const watermark = new Watermark()
watermark.init({ text: pin })

二. 方法

export default class Watermark {
  container = null
  option = {
    selector: '#watermark-container',
    // parentSelector: '#app',
    width: 300,
    height: 150,
    style: {
      'pointer-events': 'none',
      width: '100%',
      height: '100%',
      top: 0,
      left: 0,
      position: 'fixed',
      'z-index': 5000
    },
    imageStyle: {
      shadowX: 2,
      shadowY: 2,
      shadowBlur: 2,
      font: '15px Microsoft JhengHei',
      fillStyle: 'rgba(17, 17, 17, 0.07)',
      rotate: -(30 * Math.PI) / 180,
      textAlign: 'left'
    }
  }

  // 生成背景图
  createImage(option) {
    const { width, height, text } = option
    const image = document.createElement('canvas')
    image.width = width
    image.height = height

    const { shadowX, shadowY, shadowBlur, font, fillStyle, rotate, textAlign } = option.imageStyle
    const ctx = image.getContext('2d')
    ctx.shadowOffsetX = shadowX
    ctx.shadowOffsetY = shadowY
    ctx.shadowBlur = shadowBlur
    ctx.font = font
    ctx.fillStyle = fillStyle
    ctx.rotate(rotate)
    ctx.textAlign = textAlign
    ctx.fillText(text, 0, 150)

    return image.toDataURL('image/png')
  }

  // 插入水印
  createContainer(option) {
    const selectorEl = document.querySelector(option.selector)
    const isElExistence = Boolean(selectorEl)

    const div = selectorEl || document.createElement('div')
    const parentEl = option?.parentSelector ? document.querySelector(option?.parentSelector) : ''
    const fatherEl = selectorEl?.ParentNode || parentEl || document.body
    const { left = 0, top = 0 } = fatherEl.getBoundingClientRect() || {}
    const bg = this.createImage(option)

    const divSelector = option.selector?.includes('#') ? 'id' : 'className'
    div[divSelector] = option.selector?.replace(/[\#\.]*/g, '')
    div.style.left = (option.left || left) + 'px'
    div.style.top = (option.top || top) + 'px'
    div.style.cssText = this.getStyleText(option)
    div.style.background = `url(${bg}) repeat top left`

    !isElExistence && fatherEl.appendChild(div)

    return div
  }

  // 解析样式
  getStyleText(option) {
    const style = option.style
    let styleText = ''
    Object.keys(style).forEach((key) => {
      styleText += key + ': ' + style[key] + ';'
    })
    return styleText
  }

  // 视图监听
  observe(option) {
    const _that = this
    _that.container = _that.createContainer(option)
    const target = _that.container

    const newObserve = new MutationObserver(() => {
      newObserve.disconnect()
      _that.container = _that.createContainer(option)
      newObserve.observe(target, {
        attributes: true,
        childList: true,
        characterData: true,
        subtree: true
      })
    })

    newObserve.observe(target, {
      attributes: true,
      childList: true,
      characterData: true,
      subtree: false
    })
  }

  // 检测删除元素
  observeBody(option) {
    const _that = this
    const newObserve = new MutationObserver((elList) => {
      const selectorType = option.selector?.includes('#')
      const selectorValue = option.selector?.replace(/[\#\.]*/g, '')
      elList.forEach((el) => {
        if (el.type === 'childList' && el.removedNodes.length > 0) {
          let isState = false
          for (let i = 0; i < el.removedNodes.length; i++) {
            const isHasSelector = selectorType
              ? el.removedNodes[i].id === selectorValue
              : el.removedNodes[i].classList.contains(selectorValue)
            if (isHasSelector) {
              isState = true
              break
            }
          }
          if (isState) _that.observe(option)
        }
      })
    })
    newObserve.observe(document.body, { childList: true, subtree: true })
  }

  // 初始化
  init(option) {
    option = option ? Object.assign({}, this.option, option) : this.option
    this.observe(option)
    this.observeBody(option)
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值