JS中圖片壓縮的一般方法

前兩天公司業(yè)務(wù)上有需求需要將較大的圖片壓縮后再傳到遠程服務(wù)器神得,網(wǎng)上找了不少方法都不太好用厘惦,今天有空索性自己寫了一個方法,并把它放到了自己的github上哩簿,有興趣的同學可以戳這里

一宵蕉、需求是什么?

首先想一想我們有哪些需求卡骂?大多時候我們需要將一個File對象壓縮之后再變?yōu)镕ile對象傳入到遠程圖片服務(wù)器国裳;有時候我們也需要將一個base64字符串壓縮之后再變?yōu)閎ase64字符串傳入到遠程數(shù)據(jù)庫;有時候后它還有可能是一塊canvas畫布全跨,或者是一個Image對象缝左,或者直接就是一個圖片的url地址,我們需要將它們壓縮上傳到遠程浓若;面對這么多的需求渺杉,王二索性畫了一張圖:

[圖片上傳失敗...(image-d58aa3-1510824060109)]

二、解決辦法

如上圖所示挪钓,王二一共寫了七個方法是越,基本覆蓋了JS中大部分文件類型的轉(zhuǎn)換與壓縮,其中:

1碌上、urltoImage(url,fn) 會通過一個url加載所需要的圖片對象倚评,其中url參數(shù)傳入圖片的url,fn為回調(diào)方法,包含一個Image對象的參數(shù)浦徊,代碼如下:

function urltoImage (url,fn){
    var img = new Image();
    img.src = url;
    img.onload = function(){
        fn(img);
    }
};

2、imagetoCanvas(image)會將一個Image對象轉(zhuǎn)變?yōu)橐粋€Canvas類型對象天梧,其中image參數(shù)傳入一個Image對象盔性,代碼如下:

function imagetoCanvas(image){
    var cvs = document.createElement("canvas");
    var ctx = cvs.getContext('2d');
    cvs.width = image.width;
    cvs.height = image.height;
    ctx.drawImage(image, 0, 0, cvs.width, cvs.height);
    return cvs ;
};

3、canvasResizetoFile(canvas,quality,fn)會將一個Canvas對象壓縮轉(zhuǎn)變?yōu)橐粋€Blob類型對象呢岗;其中canvas參數(shù)傳入一個Canvas對象;quality參數(shù)傳入一個0-1的number類型冕香,表示圖片壓縮質(zhì)量;fn為回調(diào)方法,包含一個Blob對象的參數(shù);代碼如下:

function canvasResizetoFile(canvas,quality,fn){
    canvas.toBlob(function(blob) {
        fn(blob);
    },'image/jpeg',quality);
};

這里的Blob對象表示不可變的類似文件對象的原始數(shù)據(jù)后豫。Blob表示不一定是JavaScript原生形式的數(shù)據(jù)悉尾。 File接口基于Blob,繼承了Blob的功能并將其擴展使其支持用戶系統(tǒng)上的文件挫酿。我們可以把它當做File類型對待构眯,其他更具體的用法可以參考MDN文檔

4、canvasResizetoDataURL(canvas,quality) 會將一個Canvas對象壓縮轉(zhuǎn)變?yōu)橐粋€dataURL字符串,其中canvas參數(shù)傳入一個Canvas對象;quality參數(shù)傳入一個0-1的number類型饭豹,表示圖片壓縮質(zhì)量;代碼如下:

methods.canvasResizetoDataURL = function(canvas,quality){
    return canvas.toDataURL('image/jpeg',quality);
};

其中的 toDataURL API可以參考MDN文檔

5鸵赖、filetoDataURL(file,fn) 會將 FileBlob)類型文件轉(zhuǎn)變?yōu)?code>dataURL字符串,其中 file 參數(shù)傳入一個FileBlob)類型文件;fn為回調(diào)方法,包含一個dataURL字符串的參數(shù);代碼如下:

function filetoDataURL(file,fn){
    var reader = new FileReader();
    reader.onloadend = function(e){
        fn(e.target.result);
    };
    reader.readAsDataURL(file);
};

6拄衰、dataURLtoImage(dataurl,fn) 會將一串dataURL字符串轉(zhuǎn)變?yōu)?code>Image類型文件,其中dataurl參數(shù)傳入一個dataURL字符串,fn為回調(diào)方法它褪,包含一個Image類型文件的參數(shù),代碼如下:

function dataURLtoImage(dataurl,fn){
    var img = new Image();
    img.onload = function() {
        fn(img);
    };
    img.src = dataurl;
};

7翘悉、dataURLtoFile(dataurl) 會將一串dataURL字符串轉(zhuǎn)變?yōu)?code>Blob類型對象茫打,其中dataurl參數(shù)傳入一個dataURL字符串,代碼如下:

function dataURLtoFile(dataurl) {
    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while(n--){
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], {type:mime});
};

三、進一步封裝

對于常用的將一個File對象壓縮之后再變?yōu)?code>File對象,我們可以將上面的方法再封裝一下妖混,參考如下代碼:

function fileResizetoFile(file,quality,fn){
    filetoDataURL (file,function(dataurl){
        dataURLtoImage(dataurl,function(image){
            canvasResizetoFile(imagetoCanvas(image),quality,fn);
        })
    })
}

其中老赤,file參數(shù)傳入一個FileBlob)類型文件;quality參數(shù)傳入一個0-1number類型制市,表示圖片壓縮質(zhì)量抬旺;fn為回調(diào)方法,包含一個Blob類型文件的參數(shù)祥楣。

它使用起來就像下面這樣:

var file = document.getElementById('demo').files[0];
fileResizetoFile(file,0.6,function(res){
    console.log(res);
    //拿到res开财,做出你要上傳的操作;
})

這樣的話误褪,圖片壓縮上傳就能輕松地搞定了责鳍,以上的8個方法我已經(jīng)封裝好放到github上了,喜歡的話可以使勁的star哈兽间。

參考文檔:
MDN

原文地址:
王玉略的個人網(wǎng)站

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末历葛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子嘀略,更是在濱河造成了極大的恐慌恤溶,老刑警劉巖乓诽,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異宏娄,居然都是意外死亡问裕,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門孵坚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窥淆,你說我怎么就攤上這事卖宠。” “怎么了忧饭?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵扛伍,是天一觀的道長。 經(jīng)常有香客問我词裤,道長刺洒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任吼砂,我火速辦了婚禮逆航,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘渔肩。我一直安慰自己因俐,他們只是感情好,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布周偎。 她就那樣靜靜地躺著抹剩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蓉坎。 梳的紋絲不亂的頭發(fā)上澳眷,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音蛉艾,去河邊找鬼钳踊。 笑死,一個胖子當著我的面吹牛伺通,可吹牛的內(nèi)容都是我干的箍土。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼罐监,長吁一口氣:“原來是場噩夢啊……” “哼吴藻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弓柱,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤沟堡,失蹤者是張志新(化名)和其女友劉穎侧但,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體航罗,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡禀横,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了粥血。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柏锄。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖复亏,靈堂內(nèi)的尸體忽然破棺而出趾娃,到底是詐尸還是另有隱情,我是刑警寧澤缔御,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布抬闷,位于F島的核電站,受9級特大地震影響耕突,放射性物質(zhì)發(fā)生泄漏笤成。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一眷茁、第九天 我趴在偏房一處隱蔽的房頂上張望炕泳。 院中可真熱鬧,春花似錦蔼卡、人聲如沸喊崖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荤懂。三九已至,卻和暖如春塘砸,著一層夾襖步出監(jiān)牢的瞬間节仿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工掉蔬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留廊宪,地道東北人。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓女轿,卻偏偏與公主長得像箭启,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蛉迹,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

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