uniapp实现上传图片添加日期和地点水印,修复多张图片同时上传,显示相同图片问题

整体实现流程:首先调用uni.chooseImage方法,配置count、sizeType、sourceType参数,分别代表选择的图片个数、original 原图,compressed 压缩图,默认二者都有、是从相册还是拍照。

然后在成功的回调中拿到上传的所有图片并存储。然后就是添加水印,调用uni-getImageInfo拿图片信息,然后使用canvas进行水印添加。在成功的回调中进行图片上传(uni-uploadFile)即回显。代码如下:

imgCount就是限制上传个数,当我们同时使用拍照和相册上传,会出现当上传一张拍照图片,再从相册上传这个如果不做imgCount--操作上传的个数会出现问题。也有其他实现形式哦。

如果我们在成功的回调中拿到所有图片,直接在success中循环调用添加水印方法。例如选择了两张图片就会出现上传的两张图片一摸一样。所以我没有在success中直接遍历。 

/**选择图片*/
  selectPicture() {
    uni.chooseImage({
      count: this.imgCount,
      sizeType: ['compressed'], // 压缩图片
      sourceType: ['camera', 'album'], // 拍照或相册上传图片
      success: (res: any) => {
        this.imgCount-- // 这里主要为了限制选择的图片,解决图片先拍照上传,后有进行相册选择
        // 每次清空数组
        this.photoArr.length = 0

        // 存储上传的图片
        this.photoArr.push(...res.tempFiles.map((item: any) => item.path)) 
        // 添加水印
        this.callAddWaterMart()
      }
    })
  }

 这个callback方法就是为了在上传并添加水印后在给第二张图片添加。代码中也有注释,我就不多说了 

 // 调用添加水印的函数
  callAddWaterMart() {
    // 这个是真正的添加水印方法,传入回调是为了解决同时上传多张,会显示相同的图片。
    this.getInfoImage(() => {
      if (this.photoIndex < this.photoArr.length - 1) {
        this.photoIndex++
        this.callAddWaterMart()
      }
    })
  }

// 这里为了方便写到一个函数里
getInfoImage(callback: any) {
    // 小程序没有document,只能在页面中建一个canvas,然后在成功时给他隐藏。
    this.flag = false
    // 这个函数是可以拿到图片的一些信息,宽高等
    uni.getImageInfo({
       // 初始化photoIndex=0,拿到第一张图片,并添加水印
      src: this.photoArr[this.photoIndex],
      success: res => {
        // // 设置画布高度和宽度
        this.canvasWidth = `${res.width}px`
        this.canvasHeight = `${res.height}px`
        //获取当前时间
        let roleNameInfo = date(new Date(), 'long') + '\n' + this.from.data.address
        var ctx = uni.createCanvasContext('imgId')
        ctx.drawImage(this.photoArr[this.photoIndex], 0, 0, res.width, res.height)
        // 为图片添加水印
        ctx.setFontSize(30) //水印字体大小
        ctx.setFillStyle('red') //水印颜色
        // 水印位置
        ctx.fillText(roleNameInfo, 60, res.height - 60)
        // 开始绘制添加水印的图片并显示在页面中
        ctx.draw(false, result => {
          setTimeout(() => {
            //把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径。在自定义组件下,第二个参数传入自定义组件实例,以操作组件内  组件。
            // 这里主要为了拿到路径
            uni.canvasToTempFilePath({
              canvasId: 'imgId',
              // 设置输出的图片的宽度高度,会加快输出图片时间
              destWidth: res.width,
              destHeight: res.height,
              fileType: 'jpg', //jpg为了压缩
              quality: 0.8, //图片的质量
              success: res => {
                console.log('res', res)
                this.flag = true


                /** 添加上传进度和图片路径 */
                this.currentImgList.push({
                  path: res.tempFilePath,
                  uploadPercent: 0
                })
                // 上传图片
                this.uploadfile(res.tempFilePath)
                // 给所有的图片添加水印
                callback()
              },
              fail: err => {
                uni.hideLoading()
                // this.$u.toast('上传错误')
              }
            })
          }, 500)
        })
      },
      fail: err => {
        console.log(err)
      }
    })
  }

uploadFile我就不说了,每个公司都不一样的路径,看文档就可以了。这里只提示思路,代码大家自行实现。

你可能感兴趣的:(uni-app)