微信小程序水印

74 阅读1分钟

微信小程序写一个水印组件,直接引用到想要添加水印的页面中

<template>
  <view class="watermark-container" :style="{ position: fixed ? 'fixed' : 'absolute' }">
    <canvas 
      class="watermark-canvas" 
      :style="{ 
        width: '100%', 
        height: '100%',
        pointerEvents: 'none',
        top: '0',
        left: '0',
        zIndex: zIndex
      }"
      canvas-id="watermarkCanvas"
      @loaded="onCanvasLoaded"
    ></canvas>
  </view>
</template>

<script>
export default {
  name: 'Watermark',
  props: {
    // 水印文字内容
    text: {
      type: String,
      default: '水印文字'
    },
    // 水印文字颜色
    color: {
      type: String,
      default: 'rgba(0, 0, 0, 0.12)'
    },
    // 水印文字大小(px)
    fontSize: {
      type: Number,
      default: 12
    },
    // 水印旋转角度(度)
    rotate: {
      type: Number,
      default: -45
    },
    // 水印横向间距(px)
    gapX: {
      type: Number,
      default: 100
    },
    // 水印纵向间距(px)
    gapY: {
      type: Number,
      default: 80
    },
    // 是否固定定位
    fixed: {
      type: Boolean,
      default: true
    },
    // 层级
    zIndex: {
      type: Number,
      default: 9999
    }
  },
  data() {
    return {
      canvasContext: null,
      canvasWidth: 0,
      canvasHeight: 0
    }
  },
	mounted() {
		this.onCanvasLoaded();
	},
  methods: {
    onCanvasLoaded(e) {
			const _this = this;
      // 获取canvas上下文
      this.canvasContext = wx.createCanvasContext('watermarkCanvas', this)
      
      // 获取屏幕尺寸作为canvas尺寸
      wx.getSystemInfo({
        success: (res) => {
          _this.canvasWidth = res.windowWidth
          _this.canvasHeight = res.windowHeight
          _this.drawWatermark()
        }
      })
    },
    
    drawWatermark() {
      if (!this.canvasContext) return
      console.log(this.$store)
      const ctx = this.canvasContext
      const { color, fontSize, rotate, gapX, gapY } = this
      const text = '水印文字'
      // 清除画布
      ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
      
      // 设置文字样式
      ctx.setFontSize(fontSize)
      ctx.setFillStyle(color)
      
      // 计算文字宽度
      const textMetrics = ctx.measureText(text)
      const textWidth = textMetrics.width
      
      // 计算水印绘制范围,确保边缘也能覆盖
      const drawWidth = this.canvasWidth + gapX
      const drawHeight = this.canvasHeight + gapY
      
      // 循环绘制水印
      for (let x = -textWidth; x < drawWidth; x += gapX) {
        for (let y = 0; y < drawHeight; y += gapY) {
          // 保存当前状态
          ctx.save()
          
          // 移动到绘制位置
          ctx.translate(x, y)
          
          // 旋转文字
          ctx.rotate(rotate * Math.PI / 180)
          
          // 绘制文字
          ctx.fillText(text, 0, 0)
          
          // 恢复状态
          ctx.restore()
        }
      }
      // 绘制到画布
      ctx.draw()
    }
  },
  watch: {
    // 监听属性变化,重新绘制水印
    text: 'drawWatermark',
    color: 'drawWatermark',
    fontSize: 'drawWatermark',
    rotate: 'drawWatermark',
    gapX: 'drawWatermark',
    gapY: 'drawWatermark'
  }
}
</script>

<style scoped>
.watermark-container {
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  pointer-events: none; /* 使水印不影响下层元素交互 */
}

.watermark-canvas {
  position: absolute;
}
</style>