前端圖片壓縮常見的一些解決辦法
問題產生背景
在某一h5的項目,要求上傳的圖片格式為 base64 , 問題是用戶上傳的圖片基本都在MB 級別,轉base64 以后,圖片的體積會增大30%以上,隨著圖片的體積增加,轉換的base64 格式文件體積越大,如果此時前端不對用戶上傳的圖片體積進行壓縮,可能會導致服務器壓力過大,從而崩潰;
解決辦法
1、使用純 js 解決
解決思路:
1、通過 input 文件選擇框拿到要上傳的圖片文件file
2、FileReader.readAsDataURL() 讀取 file 內容。完成后 result 屬性中將包含一個 data: URL格式的 Base64字符串以表示所讀取文件的內容。
3、創(chuàng)建一個 img 標簽,將 FileReader 對象返回的 base64 格式 url 給到一個 img 標簽
4、img.onload() 函數(shù)中獲取圖片的尺寸,再通過 canvas.drawImage() 繪制圖像,設置尺寸或者圖像的質量等
canvas.toDataURL(file.type, quality) 設置圖像的質量,將 canvas 轉換為圖片 base64 格式
代碼如下所示:
compressImg(file) {
const reader = new FileReader();
// readAsDataURL 方法會讀取指定的 Blob 或 File 對象。讀取操作完成的時候,readyState 會變成已完成DONE,并觸發(fā) loadend (en-US) 事件,
// 同時 result 屬性將包含一個data:URL格式的字符串(base64編碼)以表示所讀取文件的內容。
reader.readAsDataURL(file);
reader.onload = () => {
const img = new Image();
img.src = reader.result;
img.onload = () => {
// 圖片的寬高
const w = img.width;
const h = img.height;
const canvas = document.createElement("canvas");
// canvas對圖片進行裁剪,這里設置為圖片的原始尺寸
canvas.width = w;
canvas.height = h;
const ctx = canvas.getContext("2d");
// canvas中,png轉jpg會變黑底,所以先給canvas鋪一張白底
ctx.fillStyle = "#fff";
// fillRect()方法繪制一個填充了內容的矩形,這個矩形的開始點(左上點)在
// (x, y) ,它的寬度和高度分別由width 和 height 確定,填充樣式由當前的fillStyle 決定。
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 繪制圖像
ctx.drawImage(img, 0, 0, w, h);
// canvas轉圖片達到圖片壓縮效果
// 返回一個包含圖片展示的 data URI base64 在指定圖片格式為 image/jpeg 或 image/webp的情況下,
// 可以從 0 到 1 的區(qū)間內選擇圖片的質量。如果超出取值范圍,將會使用默認值 0.92。其他參數(shù)會被忽略。
const dataUrl = canvas.toDataURL("image/jpeg", 0.8);
// base64格式文件轉成Blob文件格式
return blobFile = dataURLtoBlob(dataUrl);
// 拿到這個blobFile文件就可以上傳給服務端
console.log("壓縮后的file----------", blobFile);
};
};
}
// canvas生成的格式為base64,如果需要Blob格式可按如下進行轉化
dataURLtoBlob(dataurl) {
const arr = dataurl.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
},
使用以上方法存在缺點:
- 壓縮后的格式只能是 jpeg 格式,如果需要其他格式的可能需要優(yōu)化或者用別的方法
2、插件 js-image-compressor
在使用中,我們可以根據(jù)自身需求自定義配置壓縮比(quality)、輸出圖片類型(mimeType)、寬(width)、高(height)、最大寬(maxWidth)、最大高(maxHeight)、最小寬(minWidth)、最大高(minHeight)、png轉jpeg閾值(convertSize)、是否矯正jpeg方向(redressOrientation)和是否寬松模式(loose)。
● 是否矯正jpeg方向(redressOrientation),jpeg 格式圖片在某些iOS瀏覽器會按其方向呈現(xiàn)圖像,這個選項可以控制恢復初始方向,默認為 true;
● 是否寬松模式(loose)、的意思是控制當壓縮的圖片 size 大于源圖片,輸出源圖片,否則輸出壓縮后圖片,默認是 true。
以下是標準配置:
var options = {
file: file,
quality: 0.6,
mimeType: 'image/jpeg',
maxWidth: 2000,
maxHeight: 2000,
width: 1000,
height: 1000,
minWidth: 500,
minHeight: 500,
convertSize: Infinity,
loose: true,
redressOrientation: true,
// 壓縮前回調
beforeCompress: function (result) {
console.log('壓縮之前圖片尺寸大小: ', result.size);
console.log('mime 類型: ', result.type);
},
// 壓縮成功回調
success: function (result) {
console.log('壓縮之后圖片尺寸大小: ', result.size);
console.log('mime 類型: ', result.type);
console.log('實際壓縮率: ', ((file.size - result.size) / file.size * 100).toFixed(2) + '%');
},
// 發(fā)生錯誤
error: function (msg) {
console.error(msg);
}
};
new ImageCompressor(options);
以上就是插件式的解決辦法,更詳細的文檔,可以在 gitbhub 的官方文檔上查看;插件式解決辦法已經在項目中實踐,推薦大家使用~~
寫在最后
以上提供的插件式解決辦法已經在項目中實踐,但是存在的問題是,插件控制的壓縮率和實際的壓縮率有一定的出入(不同格式的圖片出入有一定差異),因此壓縮率不好嚴格控制
到此這篇關于前端圖片壓縮常見的一些解決辦法的文章就介紹到這了,更多相關前端圖片壓縮解決內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
IE中radio 或checkbox的checked屬性初始狀態(tài)下不能選中顯示問題
checked屬性在IE下不能正確實現(xiàn)的問題2009-07-07

