【微信小程序】图片压缩-纯质量压缩,非长宽裁剪压缩

9,786 阅读3分钟

原理:利用canvas来实现,将图片绘制到canvas上,然后canvas转图片时,微信提供的一个方法wx.canvasToTempFilePath(Object object, Object this),此方式可以指定生成图片的质量,下图是从官方API截的图:

其中quality可以指定图片的质量,quality的值越小,图片越模糊,通过此方法可以实现图片的压缩

注意

1.quality设置只对jpg格式的图片有效,使用时要将fileType设置为“jpg”, 此举可能会导致其它格式的图片变为jpg格式

2.透明背景的png图片,绘制到canvas上使用此方式导出的图片是黑色背景,有需求的话是需要canvas先设置背景色的,请小伙伴们注意爬坑。

有了这个参数,压缩就简单很多了,下面是代码:

wxml

<view>
  <button bindtap="chooseImage">选择图片</button>
</view>

<!-- 展示压缩后的图片 -->
<view style="display: flex;justify-content: center;flex-direction: column">
  <image mode="widthFix" src="{{imagePath}}"></image>
</view>

<button wx:if="{{imagePath.length>0}}" bindtap="save">点击下载压缩后的图片</button>

<!-- 用来渲染的canvas --> 
<canvas canvas-id='attendCanvasId' class='myCanvas' style='width:{{cWidth}}px;height:{{cHeight}}px;position: fixed;top: -9999px;left: -9999px;'></canvas>

js

Page({

  /**
   * 页面的初始数据
   */
  data: {
    imagePath: '',
    quality: 0.2,
    cWidth: 0,
    cHeight: 0,
    timer: null
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {

  },

  /**
  * 选项添加图片事件
  */
  chooseImage: function (e) {
    var that = this;
    wx.chooseImage({
      sizeType: ['compressed'],  //可选择原图或压缩后的图片
      sourceType: ['album', 'camera'], //可选择性开放访问相册、相机
      success: result => {
        wx.getImageInfo({
          src: result.tempFilePaths[0],
          success: function (res) {
            console.log(res.width, res.height)
            that.setData({
              cWidth: res.width,
              cHeight: res.height
            }, () => {
              // setData引起的页面渲染完成之后的回调函数
              // setData渲染是异步的 canvasToTempFilePath的时候canvas的大小可能还没有被重新设置
              that.getCanvasImg(result.tempFilePaths, res.width, res.height, that.data.quality);
            })
          }
        })

      }
    })

  },

  /**
   * 质量压缩
   */
  getCanvasImg(tempFilePaths, canvasWidth, canvasHeight, quality) {
    var that = this; 
    const ctx = wx.createCanvasContext('attendCanvasId');
    ctx.clearRect(0, 0, canvasWidth, canvasHeight);
    let pixelRatio = wx.getSystemInfoSync().pixelRatio
    ctx.drawImage(tempFilePaths[0], 0, 0, canvasWidth, canvasHeight);
    ctx.draw(false, function () {
      that.data.timer = setTimeout(() => {
        wx.canvasToTempFilePath({
          canvasId: 'attendCanvasId',
          fileType: 'jpg',
          quality: quality,
          destWidth: canvasWidth,
          destHeight: canvasHeight,
          success: function success(res) {
            clearTimeout(that.data.timer)
            that.setData({
              imagePath: res.tempFilePath
            });
          },
          fail: function (e) {
            clearTimeout(that.data.timer)
            wx.showModal({
              title: '提示',
              content: JSON.stringify(e),
            })
          }
        });
      }, 500)
    });
  },

  /**
   * 图片保存到相册
   */
  save(e) {
    let that = this;
    wx.saveImageToPhotosAlbum({
      filePath: that.data.imagePath,
      success: function (res) {
        console.log('图片已保存');
      },
      fail: function (res) {
        console.log('保存失败');
      }
    })
  }
})

注意点

  1. 注意设置canvas-id='attendCanvasId'
  2. canvas要离屏渲染,就是移出屏幕之外,但是元素还是显示的,position: fixed;top: -9999px;left: -9999px; 不能使用 display: none; 这样是获取不到canvas元素的。

压缩效果

微信开发者工具

百k以下

原图大小 压缩后大小
36.6Kb 9.28Kb
55.1Kb 34.4Kb
83.7Kb 14.7Kb

百k

原图大小 压缩后大小
229Kb 34.4Kb
201Kb 109Kb

Mb

原图大小 压缩后大小
2.99Mb 158Kb
4.26Mb 162Kb

安卓9

原图大小 压缩后大小
1.11Mb 290Kb
249Kb 107Kb
129Kb 110Kb

ios

原图大小 压缩后大小
310Kb 169Kb

图片越大,压缩的比例越大,建议压缩前做一个判断,百Kb以下的图片,本来就已经很小了

最后

h5页面中也有提供这样的方法

例如这样子:

let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
ctx.drawImage(imagePath, 0, 0, w, h);
canvas.toDataURL('image/jpeg', quality);

需要的小伙伴也可以自己研究研究哈...

源码-欢迎star

感谢

ok, 结束, 👏