前端压缩图片,是个常见的需求,特别是要求移动端上传图片(证件上传等),因移动网络不肯定因素,上传特别慢,须要在前端进行图片压缩再上传给服务器来保证用户体验,现就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,
};
复制代码