探究添加水印的多种方式

291 阅读2分钟

dom结构形成水印(文字+图片)

思路:

  • 设置水印的默认样式
  • 判断是否传入配置项,并且将配置项替换默认值
  • 获取页面最大宽度和长度,计算水印列数和行数,遍历创建每一个水印元素
  • 设置每一个水印的样式并添加到页面上

html部分

<template>
  <div id="app-container">
    <input type="file" @change="fileChange" />
  </div>
</template>

css部分

* {
  margin: 0;
  padding: 0;
}
#app-container {
  width: 100vw;
  height: 100vh;
}

js部分

export default {
  name: 'App',
  methods: {
    fileChange (e) {
      this.watermark({
        watermarkElement: '#app-container',
        watermarkImage: URL.createObjectURL(e.target.files[0])
      })
    },
    watermark () {
      // 默认设置
      const defaultSettings = {
        watermarkElement: 'body', // 水印填充节点
        watermarkTxt: '水印文字', // 水印文字
        watermarkImage: '', // 水印图片
        watermarkX: 20, // 水印起始位置x轴坐标
        watermarkY: 20, // 水印起始位置Y轴坐标
        watermarkRows: 2000, // 水印行数
        watermarkCols: 2000, // 水印列数
        watermarkXSpace: 70, // 水印x轴间隔
        watermarkYSpace: 30, // 水印y轴间隔
        watermarkColor: '#aaa', // 水印字体颜色
        watermarkAlpha: 0.4, // 水印透明度
        watermarkFontsize: '15px', // 水印字体大小
        watermarkFont: '微软雅黑', // 水印字体
        watermarkWidth: 210, // 水印宽度
        watermarkHeight: 80, // 水印长度
        watermarkAngle: 15 // 水印倾斜度数
      }

      // 传参覆盖默认
      if (arguments.length === 1 && typeof arguments[0] === 'object') {
        const argument = arguments[0] || {}
        const keys = Object.keys(defaultSettings)
        for (let key of keys) {
          if (defaultSettings[key] === argument[key]) {
            continue
          } else if (argument[key]) {
            defaultSettings[key] = argument[key]
          }
        }
      }

      const oTemp = document.createDocumentFragment()

      const maskElement = document.querySelector(defaultSettings.watermarkElement) || document.body

      // 获取页面最大宽度
      const pageWidth = Math.max(maskElement.scrollWidth, maskElement.clientWidth)

      // 获取页面最大高度
      const pageHeight = Math.max(maskElement.scrollHeight, maskElement.clientHeight)

      // 水印数量自适应元素区域尺寸
      defaultSettings.watermarkCols = Math.floor(pageWidth / (defaultSettings.watermarkXSpace + defaultSettings.watermarkWidth))
      defaultSettings.watermarkRows = Math.floor(pageHeight / (defaultSettings.watermarkYSpace + defaultSettings.watermarkHeight))
      let x
      let y
      for (let i = 0; i < defaultSettings.watermarkRows; i++) {
        y = defaultSettings.watermarkY + (defaultSettings.watermarkYSpace + defaultSettings.watermarkHeight) * i
        for (let j = 0; j < defaultSettings.watermarkCols; j++) {
          x = defaultSettings.watermarkX + (defaultSettings.watermarkWidth + defaultSettings.watermarkXSpace) * j
          const maskDiv = document.createElement('div')
          maskDiv.id = 'maskDiv' + i + j
          maskDiv.className = 'maskDiv'
          maskDiv.innerHTML = '<span>' + defaultSettings.watermarkTxt + '</span>'
          maskDiv.style.transform = 'rotate(-' + defaultSettings.watermarkAngle + 'deg)'
          maskDiv.style.visibility = ''
          maskDiv.style.position = 'absolute'
          maskDiv.style.left = x + 'px'
          maskDiv.style.top = y + 'px'
          maskDiv.style.overflow = 'hidden'
          maskDiv.style.zIndex = '9999'
          maskDiv.style.pointerEvents = 'none' // pointer-events:none  让水印不遮挡页面的点击事件
          maskDiv.style.opacity = defaultSettings.watermarkAlpha
          maskDiv.style.fontSize = defaultSettings.watermarkFontsize
          maskDiv.style.fontFamily = defaultSettings.watermarkFont
          maskDiv.style.color = defaultSettings.watermarkColor
          maskDiv.style.width = defaultSettings.watermarkWidth + 'px'
          maskDiv.style.height = defaultSettings.watermarkHeight + 'px'
          maskDiv.style.display = 'flex'
          maskDiv.style.justifyContent = 'center'
          maskDiv.style.alignItems = 'center'

          if (defaultSettings.watermarkImage) {
            const img = new Image()
            img.src = defaultSettings.watermarkImage
            img.style.width = 'auto'
            img.style.height = 'auto'
            img.style.maxWidth = '80%'
            img.style.maxHeight = '80%'
            maskDiv.appendChild(img)
          }
          oTemp.appendChild(maskDiv)
        }
      }
      maskElement.appendChild(oTemp)
    }
  }
}

结果示例

2022-01-17_173011.png

图片加单个水印

<input type="file" @change="fileChange" />
<img id="img">
<script>
export default {
  name: 'App',
  methods: {
    fileChange (e) {
      const img = new Image()
      img.src = URL.createObjectURL(e.target.files[0])
      img.onload = function () {
        URL.revokeObjectURL(img.src)
        const canvas = document.createElement('canvas')
        canvas.width = this.width
        canvas.height = this.height

        const ctx = canvas.getContext('2d')
        // 绘制图片到canvas
        ctx.drawImage(img, 0, 0)
        // 设置填充字号和字体,样式
        ctx.font = '24px 宋体'
        ctx.fillStyle = 'silver'
        // 设置右对齐
        ctx.textAlign = 'right'
        // 在指定位置绘制文字,这里指定距离右下角20坐标的地方
        ctx.fillText('水印文字', canvas.width - 20, canvas.height - 20)

        document.querySelector('#img').src = canvas.toDataURL()
      }
    }
  }
}
</script>

结果示例:

2022-01-17_170616.png

图片加重复水印

html部分

<template>
  <div id="app-container">
    <input type="file" @change="fileChange" />
    <img id="img">
  </div>
</template>

js部分代码

export default {
  name: 'App',
  methods: {
    createWaterMark () {
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      canvas.width = 300
      canvas.height = 200
      // 绘制之前画布清除
      ctx.clearRect(0, 0, canvas.width, canvas.height)
      // 逆时针旋转30度
      ctx.rotate(-(30 * Math.PI) / 180)
      // 设置canvas画布样式
      ctx.font = '24px 黑体'
      ctx.fillStyle = 'rgba(100, 100, 100, 0.3)'
      // 设置canvas画布文字
      ctx.fillText('水印测试', 50, 150)
      // 坐标系还原
      ctx.rotate(30 * Math.PI / 180)
      return canvas
    },
    fileChange (e) {
      const self = this
      const img = new Image()
      img.src = URL.createObjectURL(e.target.files[0])
      img.onload = function () {
        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d')
        canvas.width = this.width
        canvas.height = this.height
        ctx.drawImage(img, 0, 0)
        const waterMarkCanvas = self.createWaterMark()
        ctx.fillStyle = ctx.createPattern(waterMarkCanvas, 'repeat')
        ctx.fillRect(0, 0, canvas.width, canvas.height)
        document.querySelector('#img').src = canvas.toDataURL()
      }
    }
  }
}

结果示例

2022-01-17_215637.png