利用canvas作为媒介重新绘画一张图片达到压缩目的,由于ios存在图片翻转问题,所以需要借助exif.js对图片进行处理。
注意:base64转成file 用new File()在ios部分机型存在不兼容问题,所以转成blob,再转成file文件。
import EXIF from "exif-js";
// 压缩图片
export function changeFile(file,callback) {
var Orientation = null;
// 选择的文件是图片
if (file.type.indexOf("image") === 0) {
EXIF.getData(file, function() {
EXIF.getAllTags(this);
Orientation = EXIF.getTag(this, "Orientation");
});
// 压缩图片需要的一些元素和对象
var reader = new FileReader(),
//创建一个img对象
img = new Image();
reader.readAsDataURL(file);
// 文件base64化,以便获知图片原始尺寸
reader.onload = function(e) {
img.src = e.target.result;
};
// base64地址图片加载完毕后执行
img.onload = function() {
// 缩放图片需要的canvas(也可以在DOM中直接定义canvas标签,这样就能把压缩完的图片不转base64也能直接显示出来)
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
// 图片原始尺寸
var originWidth = this.width;
var originHeight = this.height;
// 最大尺寸限制,可通过设置宽高来实现图片压缩程度
var maxWidth = 1500,
maxHeight = 1500;
// 目标尺寸
var targetWidth = originWidth,
targetHeight = originHeight;
// 图片尺寸超过1500x1500的限制
if (originWidth > maxWidth || originHeight > maxHeight) {
if (originWidth / originHeight > maxWidth / maxHeight) {
// 更宽,按照宽度限定尺寸
targetWidth = maxWidth;
targetHeight = Math.round(
maxWidth * (originHeight / originWidth)
);
} else {
targetHeight = maxHeight;
targetWidth = Math.round(
maxHeight * (originWidth / originHeight)
);
}
}
// canvas对图片进行缩放
canvas.width = targetWidth;
canvas.height = targetHeight;
// 清除画布
context.clearRect(0, 0, targetWidth, targetHeight);
// 图片压缩
context.drawImage(img, 0, 0, targetWidth, targetHeight);
/*第一个参数是创建的img对象;第二三个参数是左上角坐标,后面两个是画布区域宽高*/
console.log("Orientation=" + Orientation);
// 图片翻转问题
if (
Orientation != "" &&
Orientation != 1 &&
Orientation != undefined
) {
switch (Orientation) {
case 6: //需要顺时针90度旋转
console.log("需要顺时针(向左)90度旋转");
rotateImg(img, "left", canvas);
break;
case 8: //需要逆时针90度旋转
console.log("需要逆时针(向右)90度旋转");
rotateImg(img, "right", canvas);
break;
case 3: //需要180度旋转
console.log("需要180度旋转");
rotateImg(img, "right", canvas);
rotateImg(img, "right", canvas);
break;
}
}
//压缩后的图片转base64 url
/*canvas.toDataURL(mimeType, qualityArgument),mimeType 默认值是'image/png';
* qualityArgument表示导出的图片质量,只有导出为jpeg和webp格式的时候此参数才有效,默认值是0.92*/
var base64 = canvas.toDataURL("image/jpeg", 0.92);
var type = "jpeg";
var fixtype = function(type) {
type = type.toLocaleLowerCase().replace(/jpg/i, "jpeg");
var r = type.match(/png|jpeg|bmp|gif/)[0];
return "image/" + r;
};
base64 = base64.replace(fixtype(type), "image/jpeg");
// 将base64转换成file对象
var base64ToFile = blobToFile( dataURLtoBlob(base64),file);
// console.log(base64ToFile)
if(callback){
callback(base64ToFile.name)
}
//var initSize = img.src.length;
// console.log("压缩前:" + initSize);
// console.log("压缩后:" + newUrl.length);
// console.log(
// "压缩率:" +
// ~~((100 * (initSize - newUrl.length)) / initSize) +
// "%"
// );
};
}
}
// 将base64转换为blob
export function dataURLtoBlob(dataurl) {
var arr = dataurl.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
// 将blob转换成file
export function blobToFile(theBlob, fileName) {
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}
// 选转图片
export function rotateImg(img, direction, canvas) {
//最小与最大旋转方向,图片旋转4次后回到原方向
const min_step = 0;
const max_step = 3;
if (img == null) return;
//img的高度和宽度不能在img元素隐藏后获取,否则会出错
let height = img.height;
let width = img.width;
let step = 2;
if (step == null) {
step = min_step;
}
if (direction == "right") {
step++;
//旋转到原位置,即超过最大值
step > max_step && (step = min_step);
} else {
step--;
step < min_step && (step = max_step);
}
//旋转角度以弧度值为参数
let degree = (step * 90 * Math.PI) / 180;
let ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, width, height);
switch (step) {
case 0:
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0);
break;
case 1:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, 0, -height);
break;
case 2:
canvas.width = width;
canvas.height = height;
ctx.rotate(degree);
ctx.drawImage(img, -width, -height);
break;
case 3:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, -width, 0);
break;
}
}