图片压缩处理

7 阅读1分钟
// 压缩函数
async function compressImage(file, maxSize = 1024 * 1024, maxWidth = 1920) {
  return new Promise((resolve, reject) => {
    if (!file.type.startsWith('image/')) {
      return;
    }

    const img = new Image();
    // 解决跨域问题(若图片来自本地/同域可省略)
    img.crossOrigin = 'anonymous';
    const reader = new FileReader();
    
    reader.onload = (e) => {
      img.src = e.target.result;
    };

    reader.onerror = () => {};

    reader.readAsDataURL(file);

    img.onload = () => {
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      if (!ctx) {
        return;
      }

      let { width, height } = img;
      if (width > maxWidth) {
        const scale = maxWidth / width;
        width = maxWidth;
        height = height * scale;
      }
      canvas.width = width;
      canvas.height = height;

      ctx.drawImage(img, 0, 0, width, height);

      let quality = 0.9; // 初始压缩质量(0-1,1为无损)
      const mimeType = file.type || 'image/jpeg'; // 默认JPG格式

      // 压缩核心函数
      function compress() {
        canvas.toBlob(
          (blob) => {
            if (!blob) {
              return;
            }

            if (blob.size <= maxSize || quality <= 0.1) {
              const randomsIdNum = uuidv4();
              const fileName = `${randomsIdNum}_${file.name.replace(/\.\w+$/, mimeType === 'image/jpeg' ? '.jpg' : '.png')}`;
              const compressedFile = new File([blob], fileName, {
                type: mimeType,
                lastModified: Date.now()
              });
              resolve(compressedFile);
              return;
            }
            quality -= 0.1;
            compress();
          },
          mimeType,
          quality
        );
      }
      compress();
    };

    img.onerror = () => {};
  });
}
// 转化成base64
async function convertFileToBase64(file) {
  return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onloadend = () => resolve(reader.result);
      reader.readAsDataURL(file);
  });
}