图片压缩后体积没变小,是我用错方法了吗?

奥哲 阅读 3

我最近在优化一个电商项目的商品详情页,发现图片加载特别慢。试了用 Canvas 做前端压缩,但生成的图片文件大小几乎没变,甚至有时候还变大了!明明原图是 2MB,压缩后还是 1.9MB 左右,完全没达到预期效果。

我用的是下面这段代码,逻辑应该没问题吧?是不是 JPEG 的质量参数没生效,还是 Canvas 本身不适合做这种压缩?

function compressImage(file, quality = 0.6) {
  return new Promise((resolve) => {
    const img = new Image();
    img.src = URL.createObjectURL(file);
    img.onload = () => {
      const canvas = document.createElement('canvas');
      canvas.width = img.width;
      canvas.height = img.height;
      const ctx = canvas.getContext('2d');
      ctx.drawImage(img, 0, 0);
      canvas.toBlob(resolve, 'image/jpeg', quality);
    };
  });
}
我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
❤海利
❤海利 Lv1
问题找到了,你这段代码根本没动图片的尺寸,只是重新画了一遍再导出,压缩效果当然不行。

Canvas 压缩的核心在于缩小尺寸,而不是单纯调 quality 参数。toBlob 的 quality 对已经压缩过的 JPEG 几乎没用,得先改变像素数量才行。

改一下,加个尺寸缩放:

function compressImage(file, quality = 0.6, maxWidth = 1920) {
return new Promise((resolve) => {
const img = new Image();
img.src = URL.createObjectURL(file);
img.onload = () => {
let { width, height } = img;

// 关键:按比例缩放尺寸
if (width > maxWidth) {
height = Math.round(height * (maxWidth / width));
width = maxWidth;
}

const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, width, height);
canvas.toBlob(resolve, 'image/jpeg', quality);
};
});
}


这样把宽度限制在 1920px,文件大小会明显降下来。

另外,如果想压得更狠,可以把 image/jpeg 换成 image/webp,同等质量下体积能小一圈。电商详情页配图 1920 宽足够展示,800-1000 其实也够用,你可以根据实际需要调这个 maxWidth 参数。
点赞
2026-03-17 18:03