微信小程序做图片压缩

功能期望:图片需要压缩至100KB以下

注意:
1 下方用大小判断是80kb,为了防止图片输出是其大小变化有误差;
2 canvas 的大小一定要动态设置,不能写死
3 为了防止用于压缩的canvas影响页面,将其绝对定位到其他地方

index.wxml

<el-button bindtap="selectImg">选择图片</el-button>
<canvas  canvas-id="myCanvas"
  style="position:fixed;right:-{{canvasW/1+300}}px;bottom:{{canvasH/1+1000}}px;width: {{canvasW}}px; height: {{canvasH}}px"></canvas>

index.js

selectImg(){
 wx.showLoading({title:"加载中"})
    util.chooseImage({
      self:this,
      endSize:100,//目标压缩至100kb以下
      success:(chooseImageRes) => {
         wx.showLoading({title:"加载中"})
		// 返回压缩后的图片
      },
      fail:err=>{
        wx.hideLoading()
        wx.showToast({
          icon:"none",
          title: '图片选择失败,请重新尝试',
        })
      }
    })
  },

util.js

function chooseImage(options) {
  const self=options.self;
  wx.chooseImage({
    count: 1,
    sizeType: ['compressed'],
    sourceType:['album', 'camera'],
    success: res => {          
      console.log('图片选择成功',new Date().getSeconds())
      let fileSize = res.tempFiles[0].size / 1024
      console.log('图fileSize',fileSize)
      const endSize=options.endSize||80;
      console.log('endSize',endSize)
      if (fileSize > endSize) {
        photoCompress({
          self:self,
          path:res.tempFiles[0].path,
          quality:8,
          endSize:endSize
        },options.success,options.fail)
        
      }else{
        photoHandle({
          self:self,
          endSize:options.endSize,
          path:res.tempFiles[0].path,
        }, options.success,options.fail)
      }
    },
    fail: err => {
      // console.log(err)
      if(options.fail) options.fail(err)
    }
  })
}
// 图片压缩
/*
self  页面this
path  图片地址,wx.getImageInfo要求path是图片的本地路径
quality 图片质量 1-10区间,因为下方会乘以0.1
callback 回调返回 (path, base64)
*/
function photoCompress(options, callback, failCallback) {
  const self=options.self;
  const path=options.path;
  const quality=options.quality;
  const endSize=options.endSize;
  console.log('photoCompress压缩开始',options)
  wx.getImageInfo({
    src: path,
    success: Infores => {
      const initW= Infores.width,initH= Infores.height;
      if(initW>initH){
        var width =  initW>800?800:initW;
        var base =initW/width;
        var height = parseInt(initH / base);
      }else{
        var height =  initH>800?800:initH;
        var base =initH/height;
        var width = parseInt(initW / base);
      }
      self.setData({
        canvas_quality:quality,
        canvasW:width,
        canvasH:height
      })
      // console.log('getImageInfo--',res,width,height,base,quality)
        let ctx = wx.createCanvasContext('myCanvas')
        ctx.drawImage(Infores.path, 0, 0, width, height)
        ctx.draw(true, () => {
          setTimeout(()=>{
            wx.canvasToTempFilePath({
              quality: quality*0.1,
              fileType: 'jpg',//quality仅对jpg有效
              canvasId: 'myCanvas',
              width: width,
              height: height,
              destWidth: width,
              destHeight: height,
              success: res => {
                // console.log('canvasToTempFilePath--',res)
                photoHandle({
                  self:self,
                  endSize:endSize,
                  path:res.tempFilePath, 
                },callback,failCallback)
                ctx.clearRect(0, 0, width, height)
              },
              fail: err => {
                // console.log('canvasToTempFilePath--fail',err)
                if(failCallback) failCallback(err)
              }
            })
          },300)
        })
    },
    fail:err=>{
     if(failCallback) failCallback(err)
    }
  })
}
// 生成base64
function photoHandle(options, callback,failCallback) {
  const self=options.self;
  const path=options.path;``
  const endSize=options.endSize;
  console.log('photoHandle',options)
  let base64Img =  'data:image/jpg;base64,' +  wx.getFileSystemManager().readFileSync(path, "base64")
  if(showSize(base64Img)/1>endSize){
    console.log('压缩后',showSize(base64Img))
    self.data.canvas_quality=self.data.canvas_quality-1;
  
    if(self.data.canvas_quality<=4){//后面备注该处处理原因
      console.log('跳出压缩',showSize(base64Img))
      callback && callback({path:path, base64:base64Img})
      return
    }
    photoCompress({
      self:self,
      path:path,
      quality:self.data.canvas_quality,
      endSize:endSize
    },callback,failCallback)
  }else{
    console.log('压缩结束',showSize(base64Img))
    callback && callback({path:path, base64:base64Img})
  }
}
// 获取base64图片大小,返回kb数字
function showSize(base64url) {
  //把头部去掉
  var str = base64url.replace('data:image/png;base64,', '');
  // 找到等号,把等号也去掉
  var equalIndex = str.indexOf('=');
  if(str.indexOf('=')>0) {
      str=str.substring(0, equalIndex);
  }
  // 原来的字符流大小,单位为字节
  var strLength=str.length;
  // 计算后得到的文件流大小,单位为字节
  var fileLength=parseInt(strLength-(strLength/8)*2);
  // 由字节转换为kb
  var size = "";
  size = (fileLength / 1024).toFixed(2);
  var sizeStr = size + ""; //转成字符串
  var index = sizeStr.indexOf("."); //获取小数点处的索引
  var dou = sizeStr.substr(index + 1, 2) //获取小数点后两位的值
  if (dou == "00") { //判断后两位是否为00,如果是则删除00                
    return sizeStr.substring(0, index) + sizeStr.substr(index + 3, 2)
  }
  return size;
}
备注:
 if(self.data.canvas_quality<=4)

防止quality过小模糊或反复的压缩无法跳出循环 最小4,该做法可能不能将图片压缩至目标值,有想过再改变canvas的宽度继续压缩,由于当前已适合业务需求,因此没有再试

实现过程中遇见的问题:

canvas绘制图片不全
原因:canvas宽高写死;
解决:canvas宽高动态读取绘制的图片的宽高对应设置

canvas绘制图片正常,图片输出不完整
现象:
检查压缩的canvas图片绘制正常且完整,但是输出的图片偶现不完整。
原因:
wx.canvasToTempFilePath 回调时机有问题,将其延迟一段时间执行

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值