微信小程序图片加水印功能开发canvas实现

2,529 阅读2分钟

一、是不是你想要的效果,可扫小程序码查看一把先:

水印小程序码.png

二、实现步骤:

1. 生成水印前的一些参数设置及图片选择:

(1)先选择要加水印的图片,可以是拍照,也可以是从相册选择;将选择的图片地址赋值给imagesrc显示到image上:

关键js代码:

   * 选择图片:
   */
  choicePic() {
    wx.chooseMedia({
      count: 1,
      mediaType: ['image'],
      maxDuration: 60,
      success: (result) => {
        console.log(result)
        this.setData({
          imgsrc: result.tempFiles[0].tempFilePath
        })
      },
      fail: (result) => {
        console.log(result)
      }
    })
  }

(2)选择完图片,点击图片可预览,关键代码:

   * 预览图片:
   */
  previewPic() {
    wx.previewImage({
      current: this.data.imgsrc,
      urls: [this.data.imgsrc],
    })
  }

(3)输入要添加的水印内容和选择字体颜色、字体大小,这个就不在此赘述,可以自己实现

(4)点击添加水印,携带选择完成的参数跳入下个生成水印的页面

2. 生成水印页面功能实现:

(1) 首先wxml中添加cavas组件(其他非关键性的组件代码就不粘贴出来了,可以自己添加):

<canvas style="position:fixed;top: 0;left: -100%" type="2d" id="Canvas"></canvas>

(2)定义data数据:

   * 页面的初始数据
   */
  data: {
    imageSrc: "",

    _canvas: null,
    ctx: null,
    _printText: undefined,
    _textLength: undefined,
    _textWidth: undefined,
    _textHeight: 120,
    _fontSize: 30,
    _canSave: false,
    _color: undefined,
  },

(3)将上个页面传过来的参数赋值给data,此处不再赘述

(4)获取canvas及cavasContext,需要计算要输入水印的宽度,用来绘制水印时候计算位置

   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    const query = wx.createSelectorQuery()
    query.select('#Canvas')
      .fields({
        node: true,
        size: true
      })
      .exec((res) => {
        const _canvas = res[0].node
        const ctx = _canvas.getContext('2d')
        this.setData({
          _canvas,
          ctx
        })
        console.log('this.data.imageSrc', this.data.imageSrc)
        // 先获取一下文字的宽:
        this.data.ctx.font = this.data._fontSize + "px serif";
        ctx.fillText(this.data._printText, -1000, -1000)
        const textWidth = ctx.measureText(this.data._printText + "").width
        this.setData({
          _textWidth: textWidth * 1.5
        })
        // 开始绘制水印:
        this.addWatermark(this.data.imageSrc)
      })
  },

(5)添加水印,并将添加后的水印图片更新到image上,直接贴代码,自己研究一下吧:

  addWatermark(tempFilePath) {
    return new Promise(async (resolve, reject) => {
      // 获取图片信息
      const imgInfo = await wx.getImageInfo({
        src: tempFilePath
      })
      // 设置canvas宽高
      this.data._canvas.width = imgInfo.width
      this.data._canvas.height = imgInfo.height
      console.log(imgInfo)
      const xSize = Math.floor(imgInfo.width / this.data._textWidth + 1)
      const ySize = Math.floor(imgInfo.height / this.data._textHeight + 1)
      console.log(ySize)
      // 创建一个图片对象
      const image = this.data._canvas.createImage();
      image.src = tempFilePath;
      image.onload = () => {
        // 将图片绘制到canvas上
        this.data.ctx.drawImage(image, 0, 0, imgInfo.width, imgInfo.height)
        // 左右各多出一半图片宽度的水印,是用来处理旋转后盖住空白部分的;上下同理:
        for (var x = 0; x < xSize * 2; x++) {
          // x控制横向多少个水印:
          for (var y = 0; y < ySize * 2; y++) {
            // y控制纵向多少个水印:
            // 绘制文字  注意::绘制斜体文字 旋转以后会发生位移,所以必须在旋转之后进行位置的调整;
            // this.drawText((x * -100), (150 * y), ((x * this.data._textWidth)), ((y * this.data._textHeight)) + 30)
            this.drawText((imgInfo.width), (imgInfo.height), -imgInfo.width / 2 + ((x * this.data._textWidth)), -imgInfo.height / 2 + ((y * this.data._textHeight)))
          }
        }
        // 将canvas转为为图片
        wx.canvasToTempFilePath({
          canvas: this.data._canvas,
          success: (res) => {
            this.setData({
              imageSrc: res.tempFilePath,
              _canSave: true
            })
            resolve(res.tempFilePath)
          },
        })
      }
    })
  },

  drawText(imgWidth, imgHeight, x, y) {
    var text = this.data._printText;
    this.data.ctx.save(); //保存原来的状态  绘制字体都是需要旋转倾斜  那么之前绘制的图片就要进行状态的保存
    // https://www.cnblogs.com/fangsmile/p/5647390.html
    this.data.ctx.globalAlpha = 0.6
    // 移动到中心点,再旋转相当于按照之前的原点旋转了
    this.data.ctx.translate(imgWidth / 2, imgHeight / 2)
    this.data.ctx.rotate(-Math.PI / 6); //绘制倾斜字体
    // 移动回原来的位置:
    this.data.ctx.translate(-imgWidth / 2, -imgHeight / 2)
    //this.data.ctx.translate(tsx, tsy); //发生位移进行位移的恢复
    this.data.ctx.font = this.data._fontSize + "px serif";
    this.data.ctx.fillStyle = this.data._color;
    this.data.ctx.fillText(text, x, y);
    this.data.ctx.restore(); //状态的恢复
  },

(6)保存图片到本地相册:

   * 保存图片:
   */
  onSavePic() {
    if (!this.data._canSave) {
      wx.showToast({
        title: '正在生成水印中,请生成后再保存',
        icon: 'none'
      })
      return
    }
    wx.saveImageToPhotosAlbum({
      filePath: this.data.imageSrc,
      success: (res) => {
        console.log(res)
        wx.showToast({
          title: '保存图片成功',
          icon: 'none'
        })
      },
      fail: (res) => {
        console.log(res)
        wx.showToast({
          title: '保存图片失败',
          icon: 'none'
        })
      }
    })
  }

三.感觉有用的话,可以打赏一把么?一毛不嫌少,100不嫌多

21673408689_.pic.jpg