使用canvas给图片加上水印

90 阅读2分钟

项目需求,在新窗口打开一张图片,图片上加上水印,我选择使用canvas生成水印蒙层

  • 遇到的问题:因为我图片是auto自适应的浏览器窗口,所以会导致水印div获取不到图片的宽度,所以我在图片上绑定load方法@load="imageLoad",等图片加载完成能获取到宽度了再生成水印。
  • 参考网站:# 使用canvas生成水印watermarkhttps://blog.csdn.net/weixin_44370837/article/details/123666313
  • 代码记录:
<template>
  <div class="preview-container">
    <div class="water-mark-con">
      <img :src="imgSrc" alt="" @load="imageLoad" />
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      imgSrc: ''
    }
  },

  created() {
    this.imgSrc = this.$route.query.path
  },
  mounted() {
    window.addEventListener('resize', this.handleResize)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.handleResize)
  },
  methods: {
    handleResize() {
      // 窗口大小改变
      this.addWaterMark()
    },
    imageLoad() {
      // 图片100%会导致获取不到width等图片加载完成
      this.addWaterMark()
    },
    addWaterMark() {
      // const watermark = {}
      // 如果水印元素已经存在先移除,再重新生成
      const id = '3.14159261111'
      if (document.getElementById(id) !== null) {
        document
          .getElementsByClassName('water-mark-con')[0]
          .removeChild(document.getElementById(id))
      }
      //  水印内容为:姓名+id
      const userInfo = JSON.parse(localStorage.getItem('userInfo'))
      const waterStr = userInfo.nickname + '(' + userInfo.id + ')'
      const canvasEle = document.createElement('canvas')
      // 动态设置单个水印元素的宽高,这决定了页面水印的密度(水印元素图片大小,要结合rotate)
      canvasEle.width = waterStr.length < 6 ? 6 * 28 : waterStr.length * 28
      canvasEle.height = waterStr.length < 6 ? 6 * 10 : waterStr.length * 10
      const ctx = canvasEle.getContext('2d') // 绘制2d图形
      ctx.rotate((-20 * Math.PI) / 180) // 设置水印元素的倾斜度, 这一行代码要写在设置水印文字之前,涉及样式的都写在设置水印文字之前
      ctx.font = '22px serif' // 设置水印文字的大小和字体
      ctx.fillStyle = 'rgba(200, 200, 200, 0.8)' // 设置水印文字的颜色
      ctx.textAlign = 'left' // 文本左对齐
      ctx.fillText(waterStr, canvasEle.width / 18, canvasEle.height / 1.1) // 设置水印文字及坐标

      // 把canvas转化为一张图片,作为背景图,添加到div
      const divEle = document.createElement('div')
      const waterMarkCon = document.getElementsByClassName('water-mark-con')[0] // 获取img图片的父级div
      const waterMarkOffsetTop = waterMarkCon.offsetTop + 'px'
      const waterMarkOffsetLeft = waterMarkCon.offsetLeft + 'px'
      divEle.id = id
      divEle.style.width = waterMarkCon.clientWidth + 'px' // 设置div元素的宽高
      divEle.style.height = waterMarkCon.clientHeight - 4 + 'px'
      divEle.style.pointerEvents = 'none'
      divEle.style.position = 'fixed'
      divEle.style.top = waterMarkOffsetTop
      divEle.style.left = waterMarkOffsetLeft
      divEle.style.background = 'url(' + canvasEle.toDataURL() + ') left top repeat'
      divEle.style.zIndex = 999999
      // div添加到body元素,水印生成
      waterMarkCon.appendChild(divEle)
    }
  }
}
</script>
<style lang="scss" scoped>
.preview-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: rgb(14, 14, 14);
}
img {
  // max-width: 100%;
  // max-height: 100%;
  // width: auto;
  // height: auto;
  max-height: 100vh;
}
</style>