圖片純前端JS壓縮的實現

張鑫旭發表於2018-11-14

本文刪簡自:www.zhangxinxu.com/wordpress/?…

一、功能體驗

先看demo:使用canvas在前端壓縮圖片並上傳demo

如下截圖:

相貌平平檔案選擇框

點選檔案選擇框,我們不妨選一張尺寸比較大的圖片,例如下面這種2M多的釣魚收穫照:

上傳演示使用的圖片

於是圖片歘歘歘地傳上去了:
上傳相關資訊截圖

此時我們點選最終上傳完畢的圖片地址,會發現原來2M多3000多畫素寬的圖片被限制為400畫素寬了:
圖片縮小後在瀏覽器中的預覽效果圖

儲存到本地會發現圖片尺寸已經變成只有70K了:
儲存到本地顯示的圖片尺寸

以上就是圖片前端壓縮並上傳demo的完整演示。

二、實現原理

要想使用JS實現圖片的壓縮效果,原理其實很簡單,核心API就是使用canvasdrawImage()方法。

Canvas本質上就是一張點陣圖,而drawImage()方法可以把一張大大的圖片繪製在小小的Canvas畫布上,不久等同於圖片尺寸壓縮了?

對於本案例的壓縮,使用的5個引數的API方法:

context.drawImage(img, dx, dy, dWidth, dHeight);
複製程式碼

各引數具體含義可以參見“Canvas API中文文件-drawImage”,這裡不展開。

舉例:
一張圖片(假設圖片物件是img)的原始尺寸是4000*3000,現在需要把尺寸限制為400*300大小,很簡單,原理如下程式碼示意:

var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = 400;
canvas.height = 300;
// 核心JS就這個context.drawImage(img,0,0,400,300);
複製程式碼

把大圖片畫在一張小畫布上,壓縮就這麼實現了,是不是簡單的有點超乎想象。

三、如果想要上傳或下載?

如果想要上傳圖片或者下載圖片,可以使用canvas.toDataURL()或者canvas.toBlob()方法先進行轉換。

1. canvas.toDataURL()
語法如下:
canvas.toDataURL(mimeType, qualityArgument)複製程式碼

可以把畫布轉換成base64格式資訊影像資訊,純字元的圖片表示法。

其中:
mimeType表示canvas匯出來的base64圖片的型別,預設是png格式,也即是預設值是'image/png',我們也可以指定為jpg格式'image/jpeg'或者webp等格式。file物件中的file.type就是檔案的mimeType型別,在轉換時候正好可以直接拿來用(如果有file物件)。
qualityArgument表示匯出的圖片質量,只要匯出為jpgwebp格式的時候此引數才有效果,預設值是0.92,是一個比較合理的圖片質量輸出引數,通常情況下,我們無需再設定。

更多關於toDataURL()方法的資訊可以參見“Canvas API中文文件-toDataURL()”。

2. canvas.toBlob()方法
語法如下:
canvas.toBlob(callback, mimeType, qualityArgument)複製程式碼

可以把畫布轉換成Blob檔案,通常用在檔案上傳中,因為是二進位制的,對後端更加友好。

toDataURL()方法相比,toBlob()方法是非同步的,因此多了個callback引數,這個callback回撥方法預設的第一個引數就是轉換好的blob檔案資訊,本文一開始的demo案例中的檔案上傳就是將canvas圖片轉換成二進位制的blob檔案,然後再ajax上傳的,程式碼如下:

// canvas轉為blob並上傳canvas.toBlob(function (blob) { 
// 圖片ajax上傳 var xhr = new XMLHttpRequest();
// 開始上傳 xhr.open("POST", 'upload.php', true);
xhr.send(blob);

});
複製程式碼

更多關於toBlob()方法的資訊可以參見“Canvas API中文文件-toBlob()”。

一旦有了可傳輸的影像資料,上傳下載就好實現了。例如下載前端壓縮好的圖片,可以參考我上一篇在掘金髮布的文章:“純JS生成並下載各種文字檔案或圖片”。

四、總結

經過“圖片→canvas壓縮→圖片”三步曲,我們完成了圖片前端壓縮功能。

以上,感謝閱讀!

來源:https://juejin.im/post/5bec3c6cf265da614312a0fa#comment

相關文章