開篇語
在我的博客,“生活”這模塊裏,經常需要上傳圖片。這些圖片一般都是我用手機拍攝的,圖片質量一般在2-5M左右。所以,我會在圖片上傳後,使用tinypng
接口進行圖片壓縮。這樣,顯示的圖片會在幾百KB左右,點擊大圖預覽纔會加載原圖。
驚人,後端竟對前端提出這樣的要求
就在前兩個月,在團隊項目裏。甲方提出了一個需求,要求對上傳的圖片進行壓縮。在我的思維邏輯裏,壓縮工作是在圖片上傳後,後端去進行處理的。
經過小組的討論分析,後端想要把圖片質量壓縮的工作放在前端去進行處理,這樣可以減少請求時間,客戶體驗感會更好。當時的有點懵逼,前端還能去處理圖片的壓縮?
常用的壓縮方法
- 圖片上傳到阿里雲或者七牛雲,雲端會壓縮圖片;
- 後端對圖片尺寸大小進行壓縮,比如
tinypng
等接口,都可以完成,但壓縮時間很久; - 前端用
Canvas
作爲媒介壓縮圖片;
顯然團隊的項目更適用於第三種方法。而且網上一大堆相關的資料。
Canvas壓縮圖片的重要知識點
詳細代碼解釋如下:
function compress (file,callback) {
var reader = new FileReader();
// 將file 對象轉成 Data URL
reader.readAsDataURL(file);
reader.onload = function(e) {
// 新建一個img 標籤(還沒嵌入DOM節點)
var image = new Image();
image.src = e.target.result;
image.onload = function() {
// canvas.getContext 進行寬高的改變,從而達到壓縮質量的目的
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
imageWidth = 300, // 壓縮質量寬度
imageHeight = 300, // 壓縮質量高度
compactData = '';
canvas.width = imageWidth;
canvas.height = imageHeight;
context.drawImage(image, 0, 0, imageWidth, imageHeight);
// 將canvas 元素所展示的圖片再次轉換成 Data URL
// 到這已經壓縮完成了
compactData = canvas.toDataURL(file.type);
// 最後把Data URL 轉成 blob
var byteString, mimeString, u8arr, blob;
if ( compactData.split(",")[0].indexOf("compactData") >= 0 ) {
byteString = atob(compactData.split(",")[1]);
} else{
byteString = unescape(compactData.split(",")[1]);
}
mimeString = compactData .split(",")[0] .split(":")[1] .split(";")[0];
u8arr = new Uint8Array(byteString.length);
for ( var i = 0; i < byteString.length; i++ ) {
u8arr[i] = byteString.charCodeAt(i);
}
blob = new Blob([u8arr], { type: mimeString });
// 返回原file 對象、壓縮後的file 對象、壓縮後的 Data URL
callback && callback(file, blob, compactData);
};
};
};
在上述樣例中,主要是經歷了圖片 -->
canvas
縮放壓縮 --> 圖片的過程。在圖片壓縮完成後,看個人所需,可以做不同的處理。例如將壓縮後的圖片顯示在頁面,作爲略縮圖,或者直接上傳壓縮圖片。
但要注意的是,上傳圖片必須是
blob
對象,所以在壓縮後,必須轉換成blob
對象才能進行上傳。轉換blob
對象的方法好幾種,原生的canvas
也提供轉換blob
的方法。有興趣可以去了解。
demo下載
- 前端壓縮圖片樣例資源下載
- 樣例地址:www.qiuzhipeng.com/resource/demo/compress.html)