JS中圖片壓縮的一般方法

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

一、需求是什么?

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

[圖片上傳失敗...(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的功能并將其擴(kuò)展使其支持用戶系統(tǒng)上的文件。我們可以把它當(dā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});
};

三、進(jìn)一步封裝

對于常用的將一個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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容