前端 图片压缩到指定大小

303 阅读1分钟

比如 300k图片 压缩到 25k

现在用的是递归压缩 并不好用 有好用的方法 可以留言 感谢

/**
 * 获取base64大小
 */
export const showSize = base64url => {
  //获取base64图片大小,返回KB数字
  var str = base64url.replace("data:image/png;base64,", "");
  var equalIndex = str.indexOf("=");
  if (str.indexOf("=") > 0) {
    str = str.substring(0, equalIndex);
  }
  var strLength = str.length;
  var fileLength = parseInt(strLength - (strLength / 8) * 2);
  // 由字节转换为KB
  var size = "";
  size = (fileLength / 1024).toFixed(2);
  var sizeStr = size + ""; //转成字符串
  var index = sizeStr.indexOf("."); //获取小数点处的索引
  var dou = sizeStr.substr(index + 1, 2); //获取小数点后两位的值
  if (dou == "00") {
    //判断后两位是否为00,如果是则删除00
    return sizeStr.substring(0, index) + sizeStr.substr(index + 3, 2);
  }
  return parseInt(size);
};
/**
 * 存储压缩图片 处理横版图片
 */
export const compressImageTotRotate = (base64, size) => {
  return new Promise(res => {
    let image = new Image();
    image.src = base64;
    // 必须先有图片才能获取宽高
    image.onload = async function() {
      const canvas = document.createElement("canvas");
      const ctx = canvas.getContext("2d");
      const { base64 } = getImageSizeQuality(
        canvas,
        ctx,
        image,
        this.width,
        this.height,
        0.6,
        size
      );
      image = null;
      res(base64);
    };
  });
};

const getImageSizeQuality = (canvas, ctx, image, w, h, quality = 0.6, size) => {
  canvas.width = w;
  canvas.height = h;
  ctx.drawImage(image, 0, 0, w, h);
  let base64 = canvas.toDataURL("image/jpeg");
  const canvasSize = showSize(base64);
  if (canvasSize > size) {
    if (canvasSize > 2000) {
      quality = 0.1;
    } else if (canvasSize > 1000) {
      quality = 0.2;
    } else if (canvasSize < 40) {
      quality = 0.9;
    }
    if (quality < 0.8) {
      quality = quality + 0.1;
    } else {
      quality = 0.9;
    }
    base64 = getImageSizeQuality(
      canvas,
      ctx,
      image,
      w * quality,
      h * quality,
      quality,
      size
    ).base64;
  }
  return { base64 };
};