前端如何壓縮圖片質量

開篇語

我的博客,“生活”這模塊裏,經常需要上傳圖片。這些圖片一般都是我用手機拍攝的,圖片質量一般在2-5M左右。所以,我會在圖片上傳後,使用tinypng接口進行圖片壓縮。這樣,顯示的圖片會在幾百KB左右,點擊大圖預覽纔會加載原圖。

驚人,後端竟對前端提出這樣的要求

就在前兩個月,在團隊項目裏。甲方提出了一個需求,要求對上傳的圖片進行壓縮。在我的思維邏輯裏,壓縮工作是在圖片上傳後,後端去進行處理的。
經過小組的討論分析,後端想要把圖片質量壓縮的工作放在前端去進行處理,這樣可以減少請求時間,客戶體驗感會更好。當時的有點懵逼,前端還能去處理圖片的壓縮?

常用的壓縮方法

  1. 圖片上傳到阿里雲或者七牛雲,雲端會壓縮圖片;
  2. 後端對圖片尺寸大小進行壓縮,比如tinypng等接口,都可以完成,但壓縮時間很久;
  3. 前端用Canvas作爲媒介壓縮圖片;

顯然團隊的項目更適用於第三種方法。而且網上一大堆相關的資料。

Canvas壓縮圖片的重要知識點

  • file對象轉成Data URL
  • 使用canvas對圖片進行縮放,從而達到壓縮質量的目的;
  • canvas元素所展示的圖片再次轉換成Data URL
  • 最後把Data URL轉成blob

詳細代碼解釋如下:

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下載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章