前端常用的小函數(shù)(2)---圖片的處理

  • 需求背景

需要從服務(wù)器讀取圖片到頁面(圖片大小未知)寨蹋,或者上傳圖片到服務(wù)器(圖片體積過大,需要壓縮) 扔茅,此外后端可能能對post請求有設(shè)置已旧。

知識羅列

1.從URL 讀取圖片信息
2.從本地上傳圖片
3.前端圖片壓縮
4.canvas 壓縮圖片的處理
5.base64轉(zhuǎn)Blob

-Talk is cheap, show me your code

handleChange = async (e, compressRatio = 0.5) => {
  const file = e.target.files[0];
  const { base64file, paddingTop } = await handleFile(file);
  const { compressedBase64File } = await handleCompressFile(
    file,
    compressRatio
  );
  const origin = base64toBlob(base64file);
  const compress = base64toBlob(compressedBase64File);
  const originSize = (origin.size / 1000).toFixed(2);
  const compressSize = (compress.size / 1000).toFixed(2);
  const compressRate = `${(
    (originSize - compressSize) /
    originSize *
    100
  ).toFixed(2)}%`;
  return {
    originStyle: {
      backgroundImage: `url(${base64file})`,
      paddingTop
    },
    compressStyle: {
      backgroundImage: `url(${compressedBase64File})`,
      paddingTop
    },
    originSize,
    compressSize,
    compressRate
  };
};

// 獲取原始圖片信息
handleFile = async file => {
  const { originFile, base64file, originSize } = await getBase64File(file);
  const { width, height } = await getImageParams(base64file);
  const paddingTop = `${height / width * 100}%`;
  return { originFile, base64file, originSize, width, height, paddingTop };
};

// 獲取壓縮圖片信息
handleCompressFile = async (file, compressRatio) => {
  const { base64file } = await getBase64File(file);
  const { width, height } = await getImageParams(base64file);
  const targetWidth = width * compressRatio;
  const targetHeight = height * compressRatio;
  // 創(chuàng)建Image 對象
  const image = new Image();
  image.src = base64file;
  // 創(chuàng)建畫布
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");
  canvas.width = targetWidth;
  canvas.height = targetHeight;

  context.fillStyle = "rgba(255,255,255,1)";
  context.fillRect(0, 0, targetWidth, targetHeight);
  context.drawImage(image, 0, 0, targetWidth, targetHeight);
  const compressedBase64File = canvas.toDataURL("image/jpeg", compressRatio);
  return { compressedBase64File };
};

// file 2 base64
getBase64File = file =>
new Promise((resolve, reject) => {
  const reader = new FileReader();
  const result = {};
  reader.readAsDataURL(file);
  reader.onload = () => {
    result.base64file = reader.result;
    result.originFile = file;
    result.originSize = file.size;
    resolve(result);
  };
  reader.onerror = error => reject(error);
});

// 通過base64file獲取圖像尺寸(把base64file換成圖片的url,即可通過url獲取圖片信息,常用來加載cdn的未知圖片)
getImageParams = base64file =>
new Promise((resolve, reject) => {
  const image = new Image();
  image.src = base64file;
  image.onload = function() {
    const width = this.width;
    const height = this.height;
    resolve({ width, height });
  };
  image.onerror = error => reject(error);
});

// 由于后端post請求的限制 召娜,可以根據(jù)具體情況確定是否 需要把 base64轉(zhuǎn)為 blob
base64toBlob = (base64file, contentType = "image/jpg", sliceSize = 512) => {
  // 參考 https://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript
  const byteCharacters = atob(base64file.split(",")[1]);
  const byteArrays = [];
  for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    const slice = byteCharacters.slice(offset, offset + sliceSize);
    const byteNumbers = new Array(slice.length);
    for (let i = 0; i < slice.length; i += 1) {
      byteNumbers[i] = slice.charCodeAt(i);
    }
    const byteArray = new Uint8Array(byteNumbers);
    byteArrays.push(byteArray);
  }
  return new Blob(byteArrays, { type: contentType });
};

$(function() {
  $("#file").on("change", async function(e) {
    const {
      originStyle,
      compressStyle,
      originSize,
      compressSize,
      compressRate
    } = await handleChange(e);

    // 原始圖片預(yù)覽
    $(".origin").css({
      "padding-top": originStyle.paddingTop,
      "background-image": originStyle.backgroundImage
    });
    // 壓縮圖片
    $(".compress").css({
      "padding-top": compressStyle.paddingTop,
      "background-image": compressStyle.backgroundImage
    });

    // 信息展示
    $(".massage").html(`
<div>原始圖片大性送省:${originSize}k</div>
<div>壓縮圖片大小:${compressSize}k</div>
<div>壓縮比:${compressRate}</div>
`);
  });
});

在線demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末玖瘸,一起剝皮案震驚了整個濱河市秸讹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌雅倒,老刑警劉巖璃诀,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蔑匣,居然都是意外死亡劣欢,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門裁良,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事仁讨〉悖” “怎么了?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵侨把,是天一觀的道長犀变。 經(jīng)常有香客問我,道長座硕,這世上最難降的妖魔是什么弛作? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮华匾,結(jié)果婚禮上映琳,老公的妹妹穿的比我還像新娘。我一直安慰自己蜘拉,他們只是感情好萨西,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著旭旭,像睡著了一般谎脯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上持寄,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天源梭,我揣著相機與錄音娱俺,去河邊找鬼。 笑死废麻,一個胖子當著我的面吹牛荠卷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播烛愧,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼油宜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了怜姿?” 一聲冷哼從身側(cè)響起慎冤,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎沧卢,沒想到半個月后蚁堤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡搏恤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年违寿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片熟空。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡藤巢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出息罗,到底是詐尸還是另有隱情掂咒,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布迈喉,位于F島的核電站绍刮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏挨摸。R本人自食惡果不足惜孩革,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望得运。 院中可真熱鬧膝蜈,春花似錦、人聲如沸熔掺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽置逻。三九已至推沸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鬓催。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工肺素, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人深浮。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓压怠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親飞苇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,095評論 25 707
  • 有個女孩說:文藝青年的話沒有一句是靠譜蜗顽,其實文藝青年想說的是:女孩的這句話布卡,完全不靠譜。 第一次見到大媽的時候雇盖,她...
    王書著閱讀 411評論 0 0
  • 終于和走南闖北的人聊會兒天忿等,我問她:“最近怎么又感冒?” 丫頭有些吃驚崔挖,問我怎么知道她感冒的贸街?我自知說走了嘴,忙打...
    a宮雨閱讀 310評論 0 1
  • 永遠最愛你的那個男人(一) 我出門在外多年以后狸相,回了老家薛匪。 每天,我下班回家后的第一...
    fun眼望世界閱讀 2,424評論 23 134
  • 在滬工作有6余年脓鹃,一般參加商會活動跟培訓學習比較多逸尖。第一次參加關(guān)于文化類祭祀活動,感受不一樣瘸右。 中國文化博...
    范琳琳123閱讀 1,832評論 2 2