修正图片角度需要EXIF.js,这里是npm安装后使用
import { EXIF } from 'exif-js';
/**
* 压缩图片
* @param {file} 输入图片
* @returns {Promise} resolved promise 返回压缩后的新图片
*/
function compressImage(file) {
return new Promise((resolve, reject) => {
// 获取图片(加载图片是为了获取图片的宽高)
const img = new Image();
img.src = window.URL.createObjectURL(file);
img.onerror = error => reject(error);
img.onload = () => {
// 画布宽高
const canvasWidth = document.documentElement.clientWidth * window.devicePixelRatio;
const canvasHeight = document.documentElement.clientHeight * window.devicePixelRatio;
// 计算缩放因子
// 这里我取水平和垂直方向缩放因子较大的作为缩放因子,这样可以保证图片内容全部可见
const scaleX = canvasWidth / img.width;
const scaleY = canvasHeight / img.height;
const scale = Math.min(scaleX, scaleY);
// 将原始图片按缩放因子缩放后,绘制到画布上
const canvas = document.createElement('canvas');
const ctx = canvas.getContext("2d");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
const imageWidth = img.width * scale;
const imageHeight = img.height * scale;
const dx = (canvasWidth - imageWidth) / 2;
const dy = (canvasHeight - imageHeight) / 2;
ctx.drawImage(img, dx, dy, imageWidth, imageHeight);
// 导出新图片
// 指定图片 MIME 类型为 'image/jpeg', 通过 quality 控制导出的图片质量,进行实现图片的压缩
const quality = 0.92
canvas.toBlob(file => resolve(tempFile), "image/jpeg", quality);
};
});
},
/**
* 修正图片旋转角度问题
* @param {file} 原图片
* @return {Promise} resolved promise 返回纠正后的新图片
*/
function fixImageOrientation (file) {
return new Promise((resolve, reject) => {
// 获取图片
const img = new Image();
img.src = window.URL.createObjectURL(file);
img.onerror = () => resolve(file);
img.onload = () => {
// 获取图片元数据(EXIF 变量是引入的 exif-js 库暴露的全局变量)
EXIF.getData(img, function() {
// 获取图片旋转标志位
var orientation = EXIF.getTag(this, "Orientation");
// 根据旋转角度,在画布上对图片进行旋转
if (orientation === 3 || orientation === 6 || orientation === 8) {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
switch (orientation) {
case 3: // 旋转180°
canvas.width = img.width;
canvas.height = img.height;
ctx.rotate((180 * Math.PI) / 180);
ctx.drawImage(img, -img.width, -img.height, img.width, img.height);
break;
case 6: // 旋转90°
canvas.width = img.height;
canvas.height = img.width;
ctx.rotate((90 * Math.PI) / 180);
ctx.drawImage(img, 0, -img.height, img.width, img.height);
break;
case 8: // 旋转-90°
canvas.width = img.height;
canvas.height = img.width;
ctx.rotate((-90 * Math.PI) / 180);
ctx.drawImage(img, -img.width, 0, img.width, img.height);
break;
}
// 返回新图片
canvas.toBlob(file => resolve(file), 'image/jpeg', 0.92)
} else {
return resolve(file);
}
});
};
});
}
/**
* 裁剪图片
* @param {file} 输入图片
* @returns {Promise} resolved promise 返回压缩后的新图片
*/
function cutImage(file) {
return new Promise((resolve, reject) => {
// 获取图片(加载图片是为了获取图片的宽高)
const img = new Image();
img.src = window.URL.createObjectURL(file);
img.onerror = error => reject(error);
img.onload = () => {
const imgWidth = img.width;
const imgHeight = img.height;
const scale = imgWidth / imgHeight;
// 这里直接把宽度除以2然后等比算出高度,如果不想每次砍一半可以自己修改
// const width1 = imgWidth - 500; 每次减500
const width1 = imgWidth / 2;
const height1 = parseInt(width1 / scale, 10);
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = width1;
canvas.height = height1;
ctx.drawImage(img, 0, 0, imgWidth, imgHeight, 0, 0, width1, height1);
canvas.toBlob(_file => resolve(_file), 'image/jpeg');
};
});
}
/**
* 本地图片预览地址
* @param {file} 原图片
* @return blob地址
*/
function getObjectURL(file) {
let url = null;
if (window.createObjcectURL !== undefined) {
url = window.createOjcectURL(file);
} else if (window.URL !== undefined) {
url = window.URL.createObjectURL(file);
} else if (window.webkitURL !== undefined) {
url = window.webkitURL.createObjectURL(file);
}
return url;
}
使用方法:
// 拍照
takePhoto = (e) => {
// 不管用什么方法获得的图片文件
const file = e.target.files[0];
if (file) {
// 先把图片旋转至正向
fixImageOrientation(file).then(fixFile => {
this.takePhotoNext(fixFile);
});
}
}
takePhotoNext = (file) => {
if (file.size > 1024 * 1024 * 4) {
// 如果图片大于4M则压缩,然后重新调用方法看是不是还大于4M,
// 大于的话继续压缩,不大于4M则裁切
compressImage(file).then(_file => {
this.takePhotoNext(_file);
});
} else {
this.cutPhoto(file);
}
}
cutPhoto = (file) => {
const img = new Image();
img.src = window.URL.createObjectURL(file);
img.onload = () => {
// 如果宽大于1920或高大于1080,重复调用至满足要求
if (img.width > 1920 || img.height > 1080) {
// 裁切图片
cutImage(file).then(_file => {
this.cutPhoto(_file);
});
} else {
// 最后的文件,想干嘛干嘛,我这里生成img的src打印出来
console.log(getObjectURL(file));
}
};
}