最近圖片庫有比較大的改動,新增了不少新方法,其中重要的一個特性就是可以 通過指定大小來壓縮圖片 ,感興趣的同學可以參考這篇文章 , 或者直接參考GitHub庫image-conversion;
前兩天公司業務上有需求需要將較大的圖片壓縮後再傳到遠端伺服器,網上找了不少方法都不太好用,今天有空索性自己寫了一個方法,並把它放到了自己的github上,有興趣的同學可以戳這裡
一、需求是什麼?
首先想一想我們有哪些需求?大多時候我們需要將一個File物件壓縮之後再變為File物件傳入到遠端圖片伺服器;有時候我們也需要將一個base64字串壓縮之後再變為base64字串傳入到遠端資料庫;有時候後它還有可能是一塊canvas畫布,或者是一個Image物件,或者直接就是一個圖片的url地址,我們需要將它們壓縮上傳到遠端;面對這麼多的需求,王二索性畫了一張圖:
二、解決辦法
如上圖所示,王二一共寫了七個方法,基本覆蓋了JS中大部分檔案型別的轉換與壓縮,其中:
1、urltoImage(url,fn)
會通過一個url載入所需要的圖片物件,其中url
引數傳入圖片的url
,fn
為回撥方法,包含一個Image物件的引數,程式碼如下:
function urltoImage (url,fn){
var img = new Image();
img.src = url;
img.onload = function(){
fn(img);
}
};
複製程式碼
2、imagetoCanvas(image)
會將一個Image
物件轉變為一個Canvas
型別物件,其中image
引數傳入一個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
物件壓縮轉變為一個Blob
型別物件;其中canvas
引數傳入一個Canvas
物件;quality
引數傳入一個0-1的number
型別,表示圖片壓縮質量;fn
為回撥方法,包含一個Blob
物件的引數;程式碼如下:
function canvasResizetoFile(canvas,quality,fn){
canvas.toBlob(function(blob) {
fn(blob);
},'image/jpeg',quality);
};
複製程式碼
這裡的
Blob
物件表示不可變的類似檔案物件的原始資料。Blob
表示不一定是JavaScript
原生形式的資料。File
介面基於Blob
,繼承了Blob
的功能並將其擴充套件使其支援使用者系統上的檔案。我們可以把它當做File型別對待,其他更具體的用法可以參考MDN文件
4、canvasResizetoDataURL(canvas,quality)
會將一個Canvas
物件壓縮轉變為一個dataURL
字串,其中canvas
引數傳入一個Canvas
物件;quality
引數傳入一個0-1的number
型別,表示圖片壓縮質量;程式碼如下:
methods.canvasResizetoDataURL = function(canvas,quality){
return canvas.toDataURL('image/jpeg',quality);
};
複製程式碼
其中的
toDataURL
API可以參考MDN文件
5、filetoDataURL(file,fn)
會將 File
(Blob
)型別檔案轉變為dataURL
字串,其中 file
引數傳入一個File
(Blob
)型別檔案;fn
為回撥方法,包含一個dataURL
字串的引數;程式碼如下:
function filetoDataURL(file,fn){
var reader = new FileReader();
reader.onloadend = function(e){
fn(e.target.result);
};
reader.readAsDataURL(file);
};
複製程式碼
6、dataURLtoImage(dataurl,fn)
會將一串dataURL
字串轉變為Image
型別檔案,其中dataurl
引數傳入一個dataURL
字串,fn
為回撥方法,包含一個Image
型別檔案的引數,程式碼如下:
function dataURLtoImage(dataurl,fn){
var img = new Image();
img.onload = function() {
fn(img);
};
img.src = dataurl;
};
複製程式碼
7、dataURLtoFile(dataurl)
會將一串dataURL
字串轉變為Blob
型別物件,其中dataurl
引數傳入一個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
物件壓縮之後再變為File
物件,我們可以將上面的方法再封裝一下,參考如下程式碼:
function fileResizetoFile(file,quality,fn){
filetoDataURL (file,function(dataurl){
dataURLtoImage(dataurl,function(image){
canvasResizetoFile(imagetoCanvas(image),quality,fn);
})
})
}
複製程式碼
其中,file
引數傳入一個File
(Blob
)型別檔案;quality
引數傳入一個0-1
的number
型別,表示圖片壓縮質量;fn
為回撥方法,包含一個Blob
型別檔案的引數。
它使用起來就像下面這樣:
var file = document.getElementById('demo').files[0];
fileResizetoFile(file,0.6,function(res){
console.log(res);
//拿到res,做出你要上傳的操作;
})
複製程式碼
這樣的話,圖片壓縮上傳就能輕鬆地搞定了,以上的8個方法我已經封裝好放到github上了,喜歡的話可以使勁的star哈。
參考文件: MDN