uinapp微信小程序图片压缩纯js不需要在html使用canvas

本文章的重点是使用了离屏canvas不需要在dom上进行显示和文件存入在本地和本地文件清理

/**
 * 离屏 Canvas 图片压缩(纯 JS 版 - 暴力清空内存版)
 * @param {String} imagePath - 原图临时路径
 * @param {Number} quality - 压缩质量 (0.8)
 */
export function compressByOffscreenCanvas(imagePath, quality = 0.8) {
  return new Promise((resolve, reject) => {
    if (typeof wx.createOffscreenCanvas !== 'function') {
      console.warn('不支持离屏 Canvas,退回原图');
      return resolve(imagePath);
    }

    wx.getImageInfo({
      src: imagePath,
      success: (info) => {
        try {
          const width = info.width;
          const height = info.height;
         //生成离屏canvas(指不在html上显示的canvs)
          const canvas = wx.createOffscreenCanvas({
            type: '2d',
            width: width,
            height: height
          });
          const ctx = canvas.getContext('2d');
          const img = canvas.createImage();
          img.src = imagePath;

          img.onload = () => {
            ctx.drawImage(img, 0, 0, width, height);
            const base64Url = canvas.toDataURL('image/jpeg', quality);
         
            const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64Url) || [];
            console.log(format,'format是文件后缀名,bodyData是base64')
            if (!bodyData) return resolve(imagePath);

            //获取本地路径
            const fs = wx.getFileSystemManager();
            const basePath = wx.env.USER_DATA_PATH;
            console.log(basePath,'获取本地根目录')
            //清理这个路径下的所有文件
            try {
              let files = fs.readdirSync(basePath);
              files.forEach(file => {
                // 只要文件名里包含 compress_ (涵盖了以前的 canvas_ 和现在的 offscreen_),全部清理
                if (file.indexOf('compress_') > -1) {
                    console.log(`${basePath}/${file}`,'1111111')
                  try {
                    fs.unlinkSync(`${basePath}/${file}`);
                    console.log('成功清理历史垃圾:', file);
                  } catch(e) {}
                }
              });
            } catch (e) {
              console.log('读取目录失败,跳过清理');
            }
            //把文件存在该路径下 
            const tempFilePath = `${basePath}/offscreen_compress_${Date.now()}.${format}`;
            console.log(tempFilePath,'1111111')
            fs.writeFile({
              filePath: tempFilePath,
              data: bodyData,
              encoding: 'base64',
              success: () => {
                console.log('离屏 Canvas 压缩并保存成功:', tempFilePath);
                resolve(tempFilePath);
              },
              fail: (err) => {
                console.error('保存文件失败,硬盘可能依旧是满的', err);
                resolve(imagePath);
              }
            });
          };

          img.onerror = () => resolve(imagePath);

        } catch (error) {
          resolve(imagePath);
        }
      },
      fail: () => resolve(imagePath)
    });
  });
}

使用方法

await compressByOffscreenCanvas(p.tempFilePath, 0.2);

 

posted @ 2026-04-25 12:00  light丶  阅读(32)  评论(0)    收藏  举报