使用Canvas API实现前端图片压缩记录

前言

最近我在工作上遇到用户上传大尺寸图片的需求,发现直接上传原始图片会消耗过多带宽和存储空间。于是在网上找了一些像 图片压缩网站 这样的工具能在浏览器里直接完成压缩,无需上传到服务器,这让我很受启发。经过研究,我找到了使用Canvas API的简单实现方案,下面是自己实现的代码和想法。

核心实现原理

Canvas图片压缩主要利用以下技术流程:

  1. 将原始图片绘制到Canvas画布上
  2. 调整Canvas尺寸以实现分辨率压缩
  3. 使用有损编码(如JPEG)和可调质量参数输出图片
  4. 将结果转换为Blob或Base64格式

关键代码实现

1. 图片加载与绘制

javascript 复制代码
function loadImage(file) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    const url = URL.createObjectURL(file);
    
    img.onload = () => {
      URL.revokeObjectURL(url);
      resolve(img);
    };
    
    img.onerror = (e) => {
      reject(e);
    };
    
    img.src = url;
  });
}

2. 核心压缩函数

javascript 复制代码
async function compressImage(file, options = {}) {
  const { 
    quality = 0.8, 
    maxWidth = 800, 
    maxHeight = 800,
    mimeType = 'image/jpeg'
  } = options;
  
  // 加载原始图片
  const img = await loadImage(file);
  
  // 计算缩放比例
  const [newWidth, newHeight] = calculateSize(img, maxWidth, maxHeight);
  
  // 创建canvas并绘制
  const canvas = document.createElement('canvas');
  canvas.width = newWidth;
  canvas.height = newHeight;
  
  const ctx = canvas.getContext('2d');
  ctx.drawImage(img, 0, 0, newWidth, newHeight);
  
  // 转换为Blob对象
  return new Promise((resolve) => {
    canvas.toBlob(
      (blob) => resolve(blob),
      mimeType,
      quality
    );
  });
}

// 辅助函数:计算新尺寸
function calculateSize(img, maxWidth, maxHeight) {
  let width = img.width;
  let height = img.height;
  
  // 计算缩放比例
  if (width > height) {
    if (width > maxWidth) {
      height = Math.round((height * maxWidth) / width);
      width = maxWidth;
    }
  } else {
    if (height > maxHeight) {
      width = Math.round((width * maxHeight) / height);
      height = maxHeight;
    }
  }
  
  return [width, height];
}

3. 使用示例

javascript 复制代码
const fileInput = document.querySelector('input[type="file"]');

fileInput.addEventListener('change', async (e) => {
  const file = e.target.files[0];
  if (!file) return;
  
  try {
    const compressedBlob = await compressImage(file, {
      quality: 0.7,
      maxWidth: 1024,
      maxHeight: 1024
    });
    
    // 使用压缩后的Blob
    console.log(`原始大小: ${file.size} bytes`);
    console.log(`压缩后: ${compressedBlob.size} bytes`);
    
    // 可以上传到服务器或提供给用户下载
  } catch (error) {
    console.error('压缩失败:', error);
  }
});

关键参数说明

  1. quality (0-1) : 控制JPEG压缩质量,数值越小压缩率越高
  2. maxWidth/maxHeight: 限制图片最大尺寸,实现分辨率压缩
  3. mimeType: 可指定为'image/jpeg'(有损)、'image/png'(无损)等

浏览器兼容性

Canvas压缩功能在现代浏览器中支持良好,包括:

  • Chrome 50+
  • Firefox 50+
  • Safari 10+
  • Edge 15+
相关推荐
kyriewen28 分钟前
白宫直接给 OpenAI 下了限制令,GPT-5.6 不能随便放出来了
前端·javascript·面试
PedroQue991 小时前
Vite插件v0.2.6:架构优化与自动化升级
前端·vite
threerocks3 小时前
什么?我连 A2A、MCP 都没学会,现在又来了 AG-UI、A2UI.
前端·aigc·ai编程
牛奶3 小时前
如何自己写一个浏览器插件?
前端·chrome·浏览器
亿元程序员4 小时前
为什么Cocos都4.0了还有人用2.x?
前端
MomentYY4 小时前
AI 到底是“懂”,还是在“猜”?
前端·人工智能·ai编程
鹏毓网络科技4 小时前
Cursor Rules 文件配置实战:3 个隐藏参数让我每月少写 40% 样板代码
前端·github
没烦恼3014 小时前
无痕模式下 HTTP\-First 拦截引发的“页面刷新”误判
前端
文心快码BaiduComate4 小时前
从个人提效到组织提效:Comate辅助构建自我进化的AI研发系统
前端·程序员
hunterandroid5 小时前
Compose 状态管理:remember、rememberSaveable 与状态提升
前端