微信小程序开发之图片压缩方案

目录

 前言:

问题:现有的压缩方案支付宝小程序不生效

解决方案:

uni.createCanvasContext(canvasId, this)

核心代码展示:

1,封装公用工具类compressImage.js

2,html调用并上传服务器:

小结:


前言:

由于公司业务拓展,急需基于uniapp生成支付宝小程序。之前已经成功将微信小程序和H5融合成一套码,故得知此需求的时候,笔者信心十足,但是本着实践出真知的想法,觉得还是得先调研一下uniapp在支付宝小程序的兼容性,并集成已有项目主体关键功能,为后续的技术调研方案做准备。在调研过程中,发现之前封装好的图片压缩方法在支付宝小程序上无法正常使用,重新阅读了官方文档后,又双更新了项目的图片压缩方法的使用流程。

问题:现有的压缩方案支付宝小程序不生效

之前封装好的压缩方案,原理是使用canvas现实的,但是在支付宝小程序端不生效,canvas相关的api存在但是不可用。

解决方案:

查阅文档后,给canvas添加了id区分支付宝小程序,可兼容之。

以下是官方文档原文

uni.createCanvasContext(canvasId, this)

#定义

画布表示,传入定义在 <canvas/> 的 canvas-id或id(支付宝小程序是id、其他平台是canvas-id)

核心代码展示:

1,封装公用工具类compressImage.js

/**
 * 给的文件资源是否小于LimitSize (M), 小于走lessCallBack, 大于走moreCallBack
 */
export function imageSizeIsLessLimitSize(imagePath, limitSize, lessCallBack, moreCallBack) {
  uni.getFileInfo({
    filePath: imagePath,

    success(res) {
      console.log('压缩前图片大小:', res.size / 1024, 'kb')

      if (res.size > 1024 * 1024 * limitSize) {
        moreCallBack()
      } else {
        lessCallBack()
      }
    }
  })
} // 主调用方法

/**
 * 获取小于限制大小的Image, limitSize默认为1M,递归调用。
 */

export function getLessLimitSizeImage(canvasId, imagePath, limitSize = 1, drawWidth, callBack) {
  imageSizeIsLessLimitSize(
    imagePath,
    limitSize,
    (lessRes) => {
      callBack(imagePath)
    },
    (moreRes) => {
      uni.getImageInfo({
        src: imagePath,
        success: function(imageInfo) {
          var maxSide = Math.max(imageInfo.width, imageInfo.height) //画板的宽高默认是windowWidth

          var windowW = drawWidth
          var scale = 1

          if (maxSide > windowW) {
            scale = windowW / maxSide
          }

          var imageW = Math.floor(imageInfo.width * scale)
          var imageH = Math.floor(imageInfo.height * scale)
          console.log('调用压缩', imageW, imageH)
          getCanvasImage(canvasId, imagePath, imageW, imageH, (pressImgPath) => {
            getLessLimitSizeImage(canvasId, pressImgPath, limitSize, drawWidth * 0.7, callBack)
          })
        }
      })
    }
  )
}
/**
 * 获取画布图片
 */

export function getCanvasImage(canvasId, imagePath, imageW, imageH, getImgsuccess) {
  const ctx = uni.createCanvasContext(canvasId)
  ctx.drawImage(imagePath, 0, 0, imageW, imageH)
  ctx.draw(false, () => {
    uni.canvasToTempFilePath({
      canvasId: canvasId,
      x: 0,
      y: 0,
      width: imageW,
      height: imageH,
      quality: 1,

      success(res) {
        getImgsuccess(res.tempFilePath)
      }
    })
  })
}
export default {
  getLessLimitSizeImage,
  imageSizeIsLessLimitSize,
  getCanvasImage
}

2,html调用并上传服务器:

<template>
  <view class="upload-page">
    <view class="upload-tips">您最多可上传{
    
    {maxCount}}张图片</view>
    <view class="image-list">
      <view v-for="(item, index) in fileList"
            :key="index"
            class="image-item">
        <image class="image"
               mode="aspectFit"
               :src="item.path"
               @click="viewImage(index)"></image>
        <image class="image-delete"
               :src="imgUrl + 'doctor/img_delete.png'"
               @tap.stop="deleteImage"
               :data-index="index"></image>
      </view>
      <view v-if="fileList.length < maxCount"
            class="image-item"
            @tap="openAlbum">
        <image class="image"
               :src="imgUrl + 'doctor/img_add.png'"></image>
      </view>
    </view>
    <view class="upload-btn"
          @tap="confirmUpload">确定</view>

    <canvas canvas-id="pressCanvas"
            id="pressCanvas"
            class="press-canvas"></canvas>
  </view>
</template>

<script>
import { getLessLimitSizeImage } from './compressImage.js'


export default {
  data() {
    return {
      imgUrl: process.env.VUE_APP_RESOURCE_URL,
      page: {
        json: {}
      },
      type: '',
      fileList: [],
      maxCount: 9
    }
  },

  components: {},
  props: {},

  onLoad(options) {
    this.type = options.type
    this.page.json = options
  },

  methods: {
    confirmUpload() {
      if (this.fileList.length === 0) {
        this.$util.showToast('请至少选择一张图片')
        return false
      }
      this.$Router.back()
      uni.$emit(this.page.json.emit, this.fileList)
    },

    // 查看图片
    viewImage(index) {
      let copyData = [],
        data = [].concat(this.fileList)
      data.forEach((v) => {
        copyData.push(v.path)
      })
      uni.previewImage({
        current: copyData[index],
        urls: copyData
      })
    },

    // 删除图片
    deleteImage(e) {
      let { index } = e.currentTarget.dataset
      this.fileList.splice(index, 1)
    },

    // 打开相册
    openAlbum() {
      let length = this.maxCount - this.fileList.length
      uni.chooseImage({
        count: length,
        sizeType: ['original', 'compressed'],
        sourceType: ['album', 'camera'],
        success: (res) => {
          this.upLoadImgs(res.tempFilePaths, this.type)
        }
      })
    },

    // 上传多张图片
    upLoadImgs(files, type) {
      uni.showLoading()
      let promises = files.map((item) => {
        return this.uploadImg(item, type)
      })
      Promise.all(promises)
        .then((datas) => {
          // 所有上传完成后
          this.fileList = datas.length > 0 && this.fileList.concat(datas)

          uni.hideLoading()
        })
        .catch(() => {
          uni.hideLoading()
        })
    },

    // 上传图片
    uploadImg(file, type) {
      return new Promise((resolve, reject) => {
        getLessLimitSizeImage('pressCanvas', file, 1, 750, (imagePath) => {
          /* #ifdef H5 */
          let devicetype = 'h5'
          /* #endif */
          /* #ifdef MP-WEIXIN */
          let devicetype = 'applet'
          /* #endif */

          /* #ifdef MP-ALIPAY */
          let devicetype = 'alipay'
          /* #endif */

          uni.uploadFile({
            url: process.env.VUE_APP_API_URL + 'client/v1/file/images',
            header: {
              'access-token': this.$store.state.user.accessToken,
              version: process.env.VUE_APP_VERSION,
              'version-code': process.env.VUE_APP_VERSION_CODE,
              devicetype: devicetype
            },
            fileType: 'image',
            filePath: imagePath,
            name: 'file',
            formData: {
              source: 'inquiryApply',
              type:  ''
            },
            success: (res) => {
              let image = JSON.parse(res.data)
              console.log('uploadFile success:', image)

              if (image.code === 200) {
                resolve(image.data[0])
              } else {
                this.$util.showModal(image.msg || '图片上传失败')
                reject(image)
              }
            },
            fail: (err) => {
              console.log('uploadFile fail:', JSON.stringify(err || {}))

              if (err.hasOwnProperty('errMsg') && err.errMsg.indexOf('timeout') > 0) {
                this.$util.showModal('上传超时,请稍后再试')
              } else {
                this.$util.showModal('图片上传失败,请稍后再试')
              }

              reject(err)
            },
            complete: () => {}
          })
        })
      })
    }
  }
}
</script>
<style lang="scss" scoped>
.upload-page {
  position: relative;
  width: 750rpx;
  height: 100vh;
  background-color: #ffffff;
}

.upload-tips {
  width: 750rpx;
  height: 80rpx;
  background-color: #fffbe8;
  font-size: 28rpx;
  color: #ed6a0c;
  line-height: 80rpx;
  text-align: center;
}

.image-list {
  box-sizing: border-box;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-items: center;
  width: 750rpx;
  padding: 30rpx;
}

.image-item {
  position: relative;
  box-sizing: border-box;
  width: 210rpx;
  height: 210rpx;
  margin-right: 30rpx;
  margin-bottom: 30rpx;
  border: 1rpx solid #ebedf0;
}

.image-item:nth-child(3n) {
  margin-right: 0;
}

.image-item .image {
  width: 210rpx;
  height: 210rpx;
}

.image-item .image-delete {
  position: absolute;
  top: -30rpx;
  right: -30rpx;
  width: 40rpx;
  height: 40rpx;
  padding: 10rpx;
}

.upload-btn {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 750rpx;
  height: 100rpx;
  background-color: $primary;
  font-size: 30rpx;
  color: #ffffff;
  line-height: 100rpx;
  text-align: center;
}

.press-canvas {
  position: absolute;
  top: -1000px;
  left: -1000px;
  background-color: gray;
  width: 750px;
  height: 750px;
}
</style>

小结:

以上就是笔者分享的图片压缩上传的方法封装及使用啦,完美兼容支付宝小程序,微信小程序及H5三端。希望对大家有所帮助。如有错误希望各位大神多多指教。

猜你喜欢

转载自blog.csdn.net/m0_61243965/article/details/126002755