前端壓縮圖片方案

導讀:

前端壓縮圖片,是個常見的需求,特別是要求移動端上傳圖片(證件上傳等),因移動網絡不肯定因素,上傳特別慢,須要在前端進行圖片壓縮再上傳給服務器來保證用戶體驗,現就canvas爲主技術來實現,下面介紹一下圖片壓縮:前端

圖片壓縮方案步驟:

  • 一、使用 window的api FileReader,對File對象進行讀取
  • 二、讀取到文件後,運用H5 canvas屬性,canvas.toDataURL 轉化成base64格式的文件,並進行壓縮,原理是qualit或像素(寬高)進行減少
  • 三、運用 Uint8Array 對象,對base64進行轉換,轉換成Files或Blob對象
  • 四、若是有須要,封裝成FormData對象

注意事項: IOS在調用canvas.toDataURL存在限制,最明顯的是長寬像素,不能超過4500,不然會出現瀏覽器崩潰現象node

import { isIos } from '../../utils/utils';
/**
 * photoCompress input前端傳入File對象,讀取成URL
 * @param file File對象
 * @param w 壓縮等參數
 * @param objDiv 生成壓縮的回調
 */
function photoCompress(file, w, objDiv) {
  const ready = new window.FileReader();
  /* 開始讀取指定的Blob對象或File對象中的內容. 當讀取操做完成時,
    readyState屬性的值會成爲DONE,若是設置了onloadend事件處理程序,
    則調用之.同時,result屬性中將包含一個data: URL格式的字符串以表示所讀取文件的內容.
  */
  ready.readAsDataURL(file);
  ready.onload = (e) => {
    const re = e.target.result;
    canvasDataURL(re, w, objDiv);
  };
}

/**
 * canvasDataURL 傳入URL,生成base64文件
 * @param path url
 * @param obj 壓縮等參數
 * @param callback 生成壓縮的回調
 */
function canvasDataURL(path, obj, callback) {
  const img = new window.Image();
  img.crossOrigin = 'Anonymous';
  img.onload = () => {
    // 默認按比例壓縮
    const w = img.width;
    const h = img.height;
    let newW = 0;
    let newH = 0;
    const scale = w / h;
    if (obj.scale) {
      newW = obj.scale * w;
      newH = newW / scale;
    } else {
      newW = obj.width || w;
      newH = obj.height || newW / scale;
    }
    if (isIos && (newW > 4500 || newH > 4500)) {
    // IOS大部分機型,在像素超過4500狀況下,使用canvas.toDataURL直接崩潰
      if (newW > newH) {
        newW = 4500;
        newH = newW / scale;
      } else {
        newH = 4500;
        newW = newH * scale;
      }
    }
    let qualit = 0.7; // 默認圖片質量爲0.7
    // 生成canvas
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    // 建立屬性節點
    const anw = document.createAttribute('width');
    anw.nodeValue = newW;
    const anh = document.createAttribute('height');
    anh.nodeValue = newH;
    canvas.setAttributeNode(anw);
    canvas.setAttributeNode(anh);
    ctx.drawImage(img, 0, 0, newW, newH);
    // 圖像質量
    if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
      qualit = obj.quality;
    }
    // quality值越小,所繪製出的圖像越模糊
    const base64 = canvas.toDataURL('image/jpeg', qualit);
    // 回調函數返回base64的值
    callback(base64);
  };
  img.src = path;
}

/**
 * 將以base64的圖片url數據轉換爲File或Blob對象
 * @param urlData 用url方式表示的base64圖片數據
 * @param fileName 文件名
 */
function convertBase64UrlToFromData(urlData, fileName) {
  const arr = urlData.split(',');
  const mime = arr[0].match(/:(.*?);/)[1];
  const bstr = window.atob(arr[1]);
  let n = bstr.length;
  const u8arr = new Uint8Array(n);
  // eslint-disable-next-line no-plusplus
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  // const blob = new window.Blob([u8arr], { type: mime });
  // blob.lastModifiedDate = new Date();
  // blob.name = 'base64File';
  const file = new window.File([u8arr], fileName || 'base64File', { type: mime });
  // file.lastModifiedDate = new Date();
  // file.name = 'base64File';
  return file;
  // const fd = new window.FormData();
  // fd.append('file', blob, `${Date.now()}.png`);
  // return fd;
}

export {
  convertBase64UrlToFromData,
  photoCompress,
};
複製代碼
相關文章
相關標籤/搜索