前端壓縮圖片,是個常見的需求,特別是要求移動端上傳圖片(證件上傳等),因移動網絡不肯定因素,上傳特別慢,須要在前端進行圖片壓縮再上傳給服務器來保證用戶體驗,現就canvas爲主技術來實現,下面介紹一下圖片壓縮:前端
注意事項: IOS在調用canvas.toDataURL存在限制,最明顯的是長寬像素,不能超過4500,不然會出現瀏覽器崩潰現象node
import { isIos } from '../../utils/utils';
/**
* photoCompress input前端傳入File對象,讀取成URL
* @param file File對象
* @param w 壓縮等參數
* @param objDiv 生成壓縮的回調
*/
function photoCompress(file, w, objDiv) {
const ready = new window.FileReader();
/* 開始讀取指定的Blob對象或File對象中的內容. 當讀取操做完成時,
readyState屬性的值會成爲DONE,若是設置了onloadend事件處理程序,
則調用之.同時,result屬性中將包含一個data: URL格式的字符串以表示所讀取文件的內容.
*/
ready.readAsDataURL(file);
ready.onload = (e) => {
const re = e.target.result;
canvasDataURL(re, w, objDiv);
};
}
/**
* canvasDataURL 傳入URL,生成base64文件
* @param path url
* @param obj 壓縮等參數
* @param callback 生成壓縮的回調
*/
function canvasDataURL(path, obj, callback) {
const img = new window.Image();
img.crossOrigin = 'Anonymous';
img.onload = () => {
// 默認按比例壓縮
const w = img.width;
const h = img.height;
let newW = 0;
let newH = 0;
const scale = w / h;
if (obj.scale) {
newW = obj.scale * w;
newH = newW / scale;
} else {
newW = obj.width || w;
newH = obj.height || newW / scale;
}
if (isIos && (newW > 4500 || newH > 4500)) {
// IOS大部分機型,在像素超過4500狀況下,使用canvas.toDataURL直接崩潰
if (newW > newH) {
newW = 4500;
newH = newW / scale;
} else {
newH = 4500;
newW = newH * scale;
}
}
let qualit = 0.7; // 默認圖片質量爲0.7
// 生成canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 建立屬性節點
const anw = document.createAttribute('width');
anw.nodeValue = newW;
const anh = document.createAttribute('height');
anh.nodeValue = newH;
canvas.setAttributeNode(anw);
canvas.setAttributeNode(anh);
ctx.drawImage(img, 0, 0, newW, newH);
// 圖像質量
if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
qualit = obj.quality;
}
// quality值越小,所繪製出的圖像越模糊
const base64 = canvas.toDataURL('image/jpeg', qualit);
// 回調函數返回base64的值
callback(base64);
};
img.src = path;
}
/**
* 將以base64的圖片url數據轉換爲File或Blob對象
* @param urlData 用url方式表示的base64圖片數據
* @param fileName 文件名
*/
function convertBase64UrlToFromData(urlData, fileName) {
const arr = urlData.split(',');
const mime = arr[0].match(/:(.*?);/)[1];
const bstr = window.atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
// eslint-disable-next-line no-plusplus
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
// const blob = new window.Blob([u8arr], { type: mime });
// blob.lastModifiedDate = new Date();
// blob.name = 'base64File';
const file = new window.File([u8arr], fileName || 'base64File', { type: mime });
// file.lastModifiedDate = new Date();
// file.name = 'base64File';
return file;
// const fd = new window.FormData();
// fd.append('file', blob, `${Date.now()}.png`);
// return fd;
}
export {
convertBase64UrlToFromData,
photoCompress,
};
複製代碼