您的位置: 首页 >日志>前端技术>详细内容

前端技术

小程序根据尺寸等比压缩图片

来源:本站原创 发布时间:2022-07-06 10:09:36 浏览次数: 【字体:

小程序根据尺寸等比压缩图片

微信小程序官方文档有「wx.compressImage」接口可以压缩图片,但只能传入压缩质量,不能根据宽高进行压缩,用户在上传文件时如果选择了3000px以上的则比较占用储存的,前台调用加载速度也会影响。

根据搜索网上相关资料,选择使用「canvas」方式进行压缩,其原理及流程如下:

1、获取原始图片的宽高

2、根据传入的压缩宽高(如果为0则不限制)要求,把图片的原始宽高等比缩小,计算出最终压缩后的图片宽高

3、使用小程序文档接口「canvas-2d」,传入图片、宽高绘制到页面中(需用样式隐藏)

4、将「wx.canvasToTempFilePath」将画布保存为图片,生成本地临时路径


已将压缩流程封装为函数,JS代码如下:

compressImage: function(path, width, height, success) {
  let that = this;
  //获取原图片信息
  wx.getImageInfo({
    src: path,
    success: function (res) {
      let canvasRatio = 1.1;
      let picWidth = res.width; //图片原始长宽
      let picHeight = res.height;
      let scale = picHeight / picWidth; //图片原始比例
      let type = res.type == 'jpeg' ? 'jpg' : res.type;
      if (width == 0 && height > 0) {
        picWidth = Math.trunc(height / scale);
        picHeight = height;
      } else if (width > 0 && height == 0) {
        picWidth = width;
        picHeight = Math.trunc(width * scale);
      } else if (width > 0 && height > 0) {
        while (picWidth > width || picHeight > height) {
          picWidth = Math.trunc(res.width / canvasRatio)
          picHeight = Math.trunc(res.height / canvasRatio)
          canvasRatio = canvasRatio + 0.1;
        }
      }
      const query = wx.createSelectorQuery().in(that);
      query.select('#compress-canvas').fields({
        node: true,
        size: true
      }).exec((res) => {
        try {
          const canvas = res[0].node;
          const ctx = canvas.getContext('2d');
          let dpr = wx.getSystemInfoSync().pixelRatio;
          //这里是设置css样式的宽高。
          //属性宽高是css样式宽高的dpr倍,兼容不同机型,避免绘制的内容模糊。
          that.setData({
            canvasWidth: picWidth / dpr,
            canvasHeight: picHeight / dpr
          })
          canvas.width = picWidth;
          canvas.height = picHeight;
          const img = canvas.createImage()
          img.src = path;
          img.onload = () => {
            ctx.drawImage(img, 0, 0, picWidth, picHeight); //先画出图片
            //延迟600ms,避免部分机型未绘制出图片内容就执行保存操作,导致最终的图片是块白色画板。
            setTimeout(() => {
              wx.canvasToTempFilePath({
                quality: 0.8,
                fileType: type,
                canvas: canvas,
                destWidth: picWidth,
                destHeight: picHeight,
                success: function (res) {
                  // wx.compressImage({
                  //   src: res.tempFilePath,
                  //   quality: 80,
                  //   success: function (res) {
                      success(res.tempFilePath);
                  //   }
                  // })
                }
              }, that)
            }, 600)
          }

        } catch (e) {
          //异常后的操作
          console.log(e);
        }
      })
    }
  })
}


调用方法:

filePath ---- 图片路径

width    ---- 需压缩的宽度

height   ---- 需压缩的高度

success ---- 压缩成功函数,返回压缩后的图片路径

this.compressImage(filePath, width, height, function(path) {
  console.log(path);
})



WXML代码:

<view class="compress-con">
  <canvas type="2d" id="compress-canvas" class="compress-canvas" style="width: {{canvasWidth}}px; height: {{canvasHeight}}px;"></canvas>
</view>


WXSS样式代码:

/* 压缩图片的画布 */
.compress-con{ position: relative; width: 0; height: 0; overflow: hidden; }
.compress-canvas{ position: absolute; z-index: -1; top: 10000rpx; left: 10000rpx; visibility: hidden; }


PS:

「wx.canvasToTempFilePath」支持传入导入的图片质量,默认写了0.8,即80。

在微信开发者工具中,画布导出的图片大小会存在异常,可能压缩后比原图还大,在真机实测中则不会出现。


语雀:https://www.yuque.com/docs/share/9a778b7f-f190-4b82-bf28-2f4ddedb65be

密码:pplg


×

用户登录