uni-app 开发小程序项目中实现前端图片压缩,实现方式

发布于:2025-07-23 ⋅ 阅读:(15) ⋅ 点赞:(0)

方式一:使用 <canvas> 实现图片压缩(推荐,兼容性好)

这是最常见的一种方式,通过将图片绘制到 <canvas> 上,然后用 canvas.toTempFilePathcanvas.toDataURL 得到压缩后的图片。

示例代码(小程序平台):

<template>
  <view>
    <button @click="chooseImage">选择图片并压缩</button>
  </view>
</template>

<script>
export default {
  methods: {
    chooseImage() {
      uni.chooseImage({
        count: 1,
        success: (res) => {
          const tempFilePath = res.tempFilePaths[0];
          this.compressImage(tempFilePath);
        }
      });
    },

    compressImage(path) {
      // 创建 canvas 实例
      const ctx = uni.createCanvasContext('myCanvas', this);
      uni.getImageInfo({
        src: path,
        success: (img) => {
          const maxW = 800; // 最大宽度
          const scale = maxW / img.width;
          const w = maxW;
          const h = img.height * scale;

          // 画图
          ctx.drawImage(path, 0, 0, w, h);
          ctx.draw(false, () => {
            // 延迟一点,确保画完
            setTimeout(() => {
              uni.canvasToTempFilePath({
                canvasId: 'myCanvas',
                destWidth: w,
                destHeight: h,
                success: (res) => {
                  console.log('压缩后图片路径:', res.tempFilePath);
                  // 可以用 res.tempFilePath 上传或预览
                },
                fail: (err) => {
                  console.error('canvas 转图片失败', err);
                }
              }, this);
            }, 200);
          });
        }
      });
    }
  }
};
</script>

<canvas canvas-id="myCanvas" style="width: 800px; height: 600px;" />

方式二:使用 uni.compressImage API(简单但压缩能力有限)

这是 uni-app 封装的一个简单压缩接口,用于压缩临时文件路径图片

uni.chooseImage({
  count: 1,
  success: (res) => {
    const filePath = res.tempFilePaths[0];
    uni.compressImage({
      src: filePath,
      quality: 80, // 取值 0 - 100,越小压缩率越高
      success: (res) => {
        console.log('压缩成功:', res.tempFilePath);
      },
      fail: (err) => {
        console.error('压缩失败:', err);
      }
    });
  }
});

注意:

  • uni.compressImage 目前只支持 App 和微信小程序平台,在 H5 和其他平台会失效或无效果。

  • 图片质量压缩效果受限,不能调整尺寸。

方式三:使用三方库(仅 H5 适用,如 compressorjs

这种方式适合在 H5 中运行的 uni-app 项目,小程序端不支持 DOM。

 

npm install compressorjs
import Compressor from 'compressorjs';

new Compressor(file, {
  quality: 0.6,
  success(result) {
    console.log('压缩后的 Blob:', result);
    // 你可以用 FileReader 或 FormData 处理这个文件
  },
  error(err) {
    console.error(err.message);
  },
});
方式 平台支持 优点 缺点
Canvas 压缩 ✅ 微信小程序、App 自由控制尺寸和质量,通用性强 需要一定代码量
uni.compressImage ✅ 微信小程序、App 简单易用 无法控制尺寸,兼容性不够
compressorjs ❌ 仅 H5 封装好,效果不错 不支持小程序环境

 最后:封装公共方法

// utils/compressImage.js

/**
 * 通用图片压缩函数(兼容小程序/APP/H5)
 * @param {String} src 原始图片路径
 * @param {Object} options 配置项 { quality, width, height }
 * @returns {Promise<String>} 返回压缩后图片路径
 */
export function compressImage(src, options = {}) {
  const { quality = 0.7, width = 800, height = null } = options;

  return new Promise((resolve, reject) => {
    // 判断运行平台
    const system = uni.getSystemInfoSync().platform;

    // 优先使用 canvas 压缩
    #ifdef MP-WEIXIN || APP-PLUS
    uni.getImageInfo({
      src,
      success(imgInfo) {
        const ratio = width / imgInfo.width;
        const targetWidth = width;
        const targetHeight = height || imgInfo.height * ratio;

        const canvasId = 'compressCanvas';
        const ctx = uni.createCanvasContext(canvasId);

        ctx.drawImage(src, 0, 0, targetWidth, targetHeight);
        ctx.draw(false, () => {
          setTimeout(() => {
            uni.canvasToTempFilePath({
              canvasId,
              destWidth: targetWidth,
              destHeight: targetHeight,
              fileType: 'jpg',
              quality,
              success(res) {
                resolve(res.tempFilePath);
              },
              fail(err) {
                reject(err);
              }
            });
          }, 200);
        });
      },
      fail: reject
    });
    #endif

    // H5 平台(用原图或者 compressorjs)
    #ifdef H5
    // 可以在此扩展 compressorjs 逻辑
    resolve(src); // 默认返回原图
    #endif
  });
}


网站公告

今日签到

点亮在社区的每一天
去签到