Skip to content

水印组件封装

解决水印模糊问题, 绘制放大2倍, 通过css 缩放50%解决。

watermark.ts 文件

ts
// src/pages/components/watermark/watermark.ts
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    text: {
      type: String,
      value: 'watermark'
    },
    fontSzie: {
      type: Number,
      value: 12
    },
    color: {
      type: String,
      value: '#D1D5DB'
    },
    angle: {
      type: Number,
      value: 25
    },
    size: {
      type: Number,
      value: wx.getSystemInfoSync().screenWidth
    },
    scale: {
      type: Number,
      value: 2
    },
    quality: {
      type: Number,
      value: 1
    },
    zIndex: {
      type: Number,
      value: 15
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    style: '',
  },
  lifetimes: {
    attached() {
      this.drawWatermark()
    }
  },
  observers: {
    text() {
      this.drawWatermark()
    }
  },
  /**
   * 组件的方法列表
   */
  methods: {
    drawWatermark() {
      const { size, scale } = this.data

      const canvas = wx.createOffscreenCanvas({
        type: '2d',
        width: size * scale,
        height: size * scale
      }) as WechatMiniprogram.Canvas

      const ctx = canvas.getContext('2d')

      ctx.scale(scale, scale)

      this.drawText(ctx)
      this.setStyle(canvas)
    },
    drawText(ctx: any) {
      const {
        text,
        fontSzie,
        angle,
        size,
        scale,
        color
      } = this.data

      ctx.font = `${fontSzie * scale}px Arial`
      ctx.fillStyle = color
      ctx.textBaseline = 'bottom'

      for (let i = 0; i < 3; i++) {
        ctx.save()
        ctx.translate(
          i * size / 3 + (i || 20) - i,
          (i + 1) * size / 3
        )
        ctx.rotate(-angle * Math.PI / 180)
        ctx.fillText(text, 0, 0)
        ctx.restore()
      }
    },
    setStyle(canvas: WechatMiniprogram.Canvas) {
      const { quality, zIndex } = this.data

      const url = canvas.toDataURL('image/png', quality)

      this.setData({
        style: `${[
          `background: url('${url}')`,
          'background-size: 50%',
          `z-index: ${zIndex}`,
        ].join(';')};`
      })
    }
  }
})
// src/pages/components/watermark/watermark.ts
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    text: {
      type: String,
      value: 'watermark'
    },
    fontSzie: {
      type: Number,
      value: 12
    },
    color: {
      type: String,
      value: '#D1D5DB'
    },
    angle: {
      type: Number,
      value: 25
    },
    size: {
      type: Number,
      value: wx.getSystemInfoSync().screenWidth
    },
    scale: {
      type: Number,
      value: 2
    },
    quality: {
      type: Number,
      value: 1
    },
    zIndex: {
      type: Number,
      value: 15
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    style: '',
  },
  lifetimes: {
    attached() {
      this.drawWatermark()
    }
  },
  observers: {
    text() {
      this.drawWatermark()
    }
  },
  /**
   * 组件的方法列表
   */
  methods: {
    drawWatermark() {
      const { size, scale } = this.data

      const canvas = wx.createOffscreenCanvas({
        type: '2d',
        width: size * scale,
        height: size * scale
      }) as WechatMiniprogram.Canvas

      const ctx = canvas.getContext('2d')

      ctx.scale(scale, scale)

      this.drawText(ctx)
      this.setStyle(canvas)
    },
    drawText(ctx: any) {
      const {
        text,
        fontSzie,
        angle,
        size,
        scale,
        color
      } = this.data

      ctx.font = `${fontSzie * scale}px Arial`
      ctx.fillStyle = color
      ctx.textBaseline = 'bottom'

      for (let i = 0; i < 3; i++) {
        ctx.save()
        ctx.translate(
          i * size / 3 + (i || 20) - i,
          (i + 1) * size / 3
        )
        ctx.rotate(-angle * Math.PI / 180)
        ctx.fillText(text, 0, 0)
        ctx.restore()
      }
    },
    setStyle(canvas: WechatMiniprogram.Canvas) {
      const { quality, zIndex } = this.data

      const url = canvas.toDataURL('image/png', quality)

      this.setData({
        style: `${[
          `background: url('${url}')`,
          'background-size: 50%',
          `z-index: ${zIndex}`,
        ].join(';')};`
      })
    }
  }
})

watermark.wxml 文件

html
<!--pages/components/watermark/watermark.wxml-->
<view class="watermark" style="{{ style }}"></view>
<!--pages/components/watermark/watermark.wxml-->
<view class="watermark" style="{{ style }}"></view>

watermark.wxss 文件

less
/* pages/components/watermark/watermark.wxss */
.watermark {
  position: fixed;
  top: 0;
  pointer-events: none;
  width: 100vw;
  height: 100vh;
}
/* pages/components/watermark/watermark.wxss */
.watermark {
  position: fixed;
  top: 0;
  pointer-events: none;
  width: 100vw;
  height: 100vh;
}