首页 > 编程语言 >微信小程序 图片压缩

微信小程序 图片压缩

时间:2024-03-31 21:25:53浏览次数:22  
标签:canvas resolve 微信 压缩 param res path 图片 size

主要是通过canvas进行压缩 兼容wx.compressImage API
wx.compressImage 还没测试,canvas 缩放宽高比才能达到压缩

utils/compressImage.js

// compressImage.js
/**
 * @param {object} img 包含path:图片的path,size:图片的大小
 * @param {object} canvas canvas对象
 * @param {number} fileLimit 文件大小限制
 * @returns {Promise} 返回Promise对象
 */
function _compressImage(img, canvas, fileLimit) {
    return wx.getSystemInfo().then(res => {
      let {
        // 设备像素比
        pixelRatio,
        // 设备品牌
        system
      } = res;
      // 是否是IOS系统
      let isIOS = /(ios)/ig.test(system);
      // 文件限制
      fileLimit = fileLimit || 2 * 1024 * 1024;
      // 基础大小
      let baseSize = 1280;
      // 大于文件限制,手动压缩
      if (img.size > fileLimit) {
        return compressImg({src:img.path, size:img.size, canvas, baseSize, isIOS, pixelRatio}).then(response => {
          return Promise.resolve(response);
        });
      }
      return Promise.resolve(img.path);
    });
  }
  
  /**
   * @description 根据图片的大小选择压缩的方式
   * @param {string} src 图片的path
   * @param {number} size 图片的大小
   * @param {object} canvas canvas对象
   * @param {number} baseSize 基础尺寸
   * @param {boolean} isIOS 是否是IOS系统 
   * @returns {Promise} 返回Promise对象
   */
  function compressImg({src, size, canvas, baseSize, isIOS, pixelRatio}) {
    return new Promise((resolve, reject) => {
      wx.getImageInfo({
        src
      }).then(res => {
        let imgWidth = res.width;
        let imgHeight = res.height;
        if (imgWidth <= 4096 && imgHeight <= 4096) {
          // 小于4096使用canvas压缩
          canvasToImage({src, size, imgWidth, imgHeight, canvas, baseSize, isIOS, pixelRatio}).then(response => {
            resolve(response);
          });
        } else {
          // 超过4096使用强制压缩
          compressImage(src, size, isIOS).then(response => {
            resolve(response);
          });
        }
      }).catch(err => {
        // 使用强制压缩
        compressImage(src, size, isIOS).then(response => {
          resolve(response);
        });
      });
    });
  }
  
  /**
   * @description 使用wx.compressImage压缩图片
   * @param {string} src 图片的path
   * @param {number} size 图片的大小
   * @param {boolean} isIOS 是否是IOS系统
   * @returns {Promise} 返回Promise对象
   */
  function compressImage(src, size, isIOS) {
    return new Promise((resolve, reject) => {
      let quality = 100;
      if (isIOS) {
        quality = 0.1;
      } else {
        let temp = 30 - (size / 1024 / 1024);
        quality = temp < 10 ? 10 : temp;
      }
      wx.compressImage({
        src,
        quality,
        success: (res) => {
          resolve(res.tempFilePath);
        },
        fail: () => {
          // 压缩失败返回传递的图片src
          resolve(src);
        }
      });
    });
  }
  
  /**
   * @description 使用canvans压缩图片
   * @param {string} src 图片的path
   * @param {number} size 图片的大小
   * @param {number} imgWidth 图片的宽度
   * @param {number} imgHeight 图片的高度
   * @param {object} canvas canvas对象
   * @param {number} baseSize 基础尺寸
   * @param {boolean} isIOS 是否是IOS系统
   * @param {number} pixelRatio 设备像素比
   * @returns {Promise} 返回Promise对象
   */
  function canvasToImage({src, size, imgWidth, imgHeight, canvas, baseSize, isIOS, pixelRatio}) {
    return new Promise((resolve, reject) => {
      if (!canvas) {
        compressImage(src, size).then(res => {
          resolve(res);
        });
        return;
      }
      // 设置canvas宽度和高度
      let canvasWidth = 0;
      let canvasHeight = 0;
      let quality = 1;
      // 图片的宽度和高度都小于baseSize,宽高不变
      if (imgWidth <= baseSize && imgHeight <= baseSize) {
        canvasWidth = imgWidth;
        canvasHeight = imgHeight;
        quality = 0.4;
      } else {
        let compareFlag = true;
        // 图片的一边大于baseSize,宽高不变
        if (pixelRatio > 2 && (imgWidth > baseSize || imgHeight > baseSize) && (imgWidth < baseSize || imgHeight < baseSize)) {
          canvasWidth = imgWidth;
          canvasHeight = imgHeight;
          quality = 0.4;
        } else {
          // 按照原图的宽高比压缩
          compareFlag = pixelRatio > 2 ? (imgWidth > imgHeight) : (imgWidth > imgHeight);
          // 宽比高大,宽按基准比例缩放,高设置为基准值,高比宽大,高按基准比例缩放,宽设置为基准值。
          canvasWidth = compareFlag ? parseInt(imgWidth / (imgHeight / baseSize)) : baseSize;
          canvasHeight = compareFlag ? baseSize : parseInt(imgHeight / (imgWidth / baseSize));
          quality = 0.4;
        }
      }
      //将画布缩小,否则质量还是很大
      canvasWidth = canvasWidth * quality
      canvasHeight = canvasHeight * quality
      //宽高必须和绘制尺寸一样。否则展示不全
      canvas.width = canvasWidth;
      canvas.height = canvasHeight;
      let pic = canvas.createImage();
      pic.src = src;
      pic.onerror = function () {
        // 加载失败使用强制压缩
        compressImage(src, size, isIOS).then(response => {
          resolve(response);
        });
      }
      pic.onload = function () {
        // 获取绘画上下文
        let ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, canvasWidth, canvasHeight);
        ctx.drawImage(pic, 0, 0, canvasWidth, canvasHeight);
        // 导出图片
        wx.canvasToTempFilePath({
          canvas,
          width: canvasWidth,
          height: canvasHeight,
          destHeight: canvasHeight,
          destWidth: canvasWidth,
          fileType:'jpg',
          quality,
          success: (res) => {
            resolve(res.tempFilePath);
          },
          fail: (err) => {
            // 压缩失败使用强制压缩
            compressImage(src, size, isIOS).then(response => {
              resolve(response);
            });
          }
        });
      }
    });
  }
  
  /**
   * @description 循环压缩图片
   * @param {object} img 包含path:图片的path,size:图片的大小
   * @param {object} canvas canvas对象
   * @param {number} fileLimit 文件大小限制
   * @returns {Promise} 返回Promise对象
   */
  async function cycleCompressImg(img, canvas, fileLimit) {
    let fileSystemManager = wx.getFileSystemManager();
  
    function getFileInfoPromise(src) {
      return new Promise((resolve, reject) => {
        fileSystemManager.getFileInfo({
          filePath: src,
          success: (res) => {
            resolve(res);
          },
          fail: (err) => {
            reject(err);
          }
        });
      });
    }
    let size = await getFileInfoPromise(img.path).size;
    let path = img.path;
    while (size > fileLimit) {
      path = await _compressImage(img, canvas, fileLimit);
    }
    return path;
  }
  
  module.exports = {
    _compressImage,
    cycleCompressImg
  };
  

wxml

<canvas type="2d" id="uploadCanvas" class="canvas" ></canvas>

wxss

.canvas {
    width: 100rpx;
    height: 100rpx;
    opacity: 0;
    position: absolute;
    z-index: -1;
    display: none;
  }
  

js

const {
    compressImage ,
    _compressImage
    } = require('../../utils/compressImage.js');
    
	Page({
	
	  //获取文件信息
  getFileInfo(path){
    return new Promise((resolve, reject) => {
        wx.getFileSystemManager().getFileInfo({
            filePath:path,
            success(rr){
                resolve(rr)
            },
            fail(err){
                reject(err)
            }
          })
    })
  },
  //选择图片
  chooseImg(e) {
    const { id } = e.currentTarget.dataset
    if (this.data[id]) {
      return
    }
    const that = this
    // 选择图片
    wx.chooseImage({
      sizeType: ['compressed'],
      sourceType: ['album', 'camera'],
      count: 1,
      success:  async (res)=> {
         let path = res.tempFilePaths[0]
        //  如果大于1mb则去压缩
         if (res.tempFiles[0].size > 1 * 1024 * 1024) {
            let canvas = await that.getCanvas('uploadCanvas')
            if (canvas) {
			//此处1 * 1024 * 1024 是否大于1mb,大于则压缩
                path = await _compressImage(res.tempFiles[0], canvas, 1 * 1024 * 1024)
                let fileInfo =  await that.getFileInfo(path) 
                if (fileInfo.size > 1 * 1024 * 1024 ) {//判断是否压缩过后依然大于1mb
                    wx.showToast({
                        title: '上传图片文件必须小于5MB',  //因为根据压缩比例,5mb的文件通过压缩后大概有几百k,所以实际上传能有5mb
                        icon: "none"
                    })
                    return
                }
            }
        }
        that.setData({
            [id]: path
        })
      }
    })
  },
  // 获取canvas,用于压缩图片
  getCanvas(id) {
    return new Promise((resolve, reject) => {
      let query = wx.createSelectorQuery();
      query.in(this);
      query.select(`#${id}`).fields({
        node: true,
        size: true
      }).exec((res) => {
        if (res[0]) {
          resolve(res[0].node);
        } else {
          resolve(null);
        }
      });
    });
  },
	})

标签:canvas,resolve,微信,压缩,param,res,path,图片,size
From: https://www.cnblogs.com/wxyblog/p/18107260

相关文章

  • java毕业设计基于微信公交查询小程序设计与实现
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:随着移动互联网技术的飞速发展,智能手机已经成为人们日常生活中不可或缺的一部分。微信作为国内领先的即时通讯软件,其小程序功能为用户提供了便捷的服务和......
  • Python之Opencv进阶教程(2):统计图片灰度级别的像素数量
    1、什么是灰度像素数量在OpenCV中,可以使用**cv2.calcHist()**函数来计算图像的直方图。直方图是一种图形统计表,用于表示图像中每个灰度级别(或颜色通道)的像素数量或密度分布。以下是一个示例代码,演示了如何使用OpenCV计算和绘制图像的直方图:2、代码importcv2ascvimpor......
  • Python之Opencv进阶教程(1):图片模糊
    1、Opencv提供了多种模糊图片的方法加载原始未经模糊处理的图片importcv2ascvimg=cv.imread('../Resources/Photos/girl.jpg')cv.imshow('girl',img)1.1平均值关键代码#Averaging平均值a......
  • 微信小程序引导组件【添加到我的小程序】
    微信小程序引导组件,点击按钮,弹窗引导用户【添加到我的小程序】源代码https://ext.dcloud.net.cn/plugin?id=17303......
  • 【全开源】JAVA上门家政服务系统源码微信小程序+微信公众号+APP+H5_博纳软云
    上门家政服务系统源码微信小程序——让便捷服务触手可及在现代社会,家政服务的需求日益增长,而如何快速、便捷地找到优质的家政服务成为了许多家庭关注的焦点。为此,我们推出了上门家政服务系统源码微信小程序,让便捷服务触手可及。这款微信小程序不仅集成了丰富的家政服务资源,还......
  • 【全开源】无人共享棋牌室茶室台球室系统JAVA版本支持微信小程序+微信公众号_博纳软云
    在繁忙的都市生活中,寻找一处静谧的棋牌室、茶室或台球室,已成为许多人放松身心、享受闲暇时光的理想选择。为满足这一市场需求,我们推出了无人共享棋牌室茶室台球室系统JAVA版本,支持微信小程序和微信公众号,为您带来全新的智能体验。该系统采用先进的JAVA技术开发,实现了无人值守......
  • 【全开源】无人共享棋牌室茶室台球室系统JAVA版本支持微信小程序+微信公众号_博纳软云
    在繁忙的都市生活中,寻找一处静谧的棋牌室、茶室或台球室,已成为许多人放松身心、享受闲暇时光的理想选择。为满足这一市场需求,我们推出了无人共享棋牌室茶室台球室系统JAVA版本,支持微信小程序和微信公众号,为您带来全新的智能体验。该系统采用先进的JAVA技术开发,实现了无人值守......
  • qrcodejs2 首次生成微信支付二维码不渲染问题
    使用qrcodejs2生成微信支付二维码,后端向前端传递了微信二维码url,通过此方法生成渲染二维码图片  qrcode(url){ //前端根据URL生成微信支付二维码   console.log("调用二维码生成")   //先清除,后增加   document.getElementById("qrcodeIm......
  • 【全开源】短剧系统微信小程序+H5+微信公众号+APP 源码_博纳软云
    短剧系统,汇聚微信小程序、H5、微信公众号与APP的源码精髓,犹如一股清新的文化风潮,席卷而来,让人眼前一亮。在这个信息爆炸的时代,短剧以其短小精悍、内容丰富的特点,成为了大众娱乐的新宠。而短剧系统,正是为了满足人们对于短剧内容的渴求,应运而生。它打破了传统媒体的束缚,将短剧内......
  • Vue怎么使用Upload组件进行图片上传到阿里云OSS,并
    基于前端用Vue2后端用Springboot进行讲解一、创建阿里云OSS       对象存储OSS_云存储服务_企业数据管理_存储-阿里云(aliyun.com),打开网站进行开通    开通后我们来到Bucket列表,创建Bucket            创建过程:后面就默认就行了   ......