移动端图片上传的时候,都是手机本地图片,而本地图片一般都是1、2M左右,所以有必要按一定的比例压缩后上传。
图片压缩
1、input file上传图片的时候,用filereader读取用户上传的图片数据(base64格式)
2、把图片数据传入img对象,然后将img绘制到canvas上,再调用canvas.toDataURL对图片进行压缩。toDataURL()方法返回一个包含图片展示的 data URI ,使用两个参数,第一个参数为图片格式,默认为 image/png。第二个参数为压缩质量,在指定图片格式为 image/jpeg或 image/webp的情况下,可以从0到1的区间内选择图片的质量。
3、获取到压缩后的base64格式图片数据Ajax上传,或者是转成二进制塞入formdata,再通过Ajax提交formdata。
图片旋转
移动端上传拍照图片后,会发现有些图片的方向不对,这些是因为拍摄方向不同造成的。解决这个问题的思路是利用Exif.js获取到照片拍摄的方向,然后利用canvas.rotate对照片进行角度旋转修正。
Exif.js
Exif.js提供了JavaScript读取图像的原始数据的功能扩展,例如:拍摄方向、相机设备型号、拍摄时间、ISO 感光度、GPS 地理位置等数据。
注:EXIF数据主要来自拍摄的照片,多用于移动端开发,PC 端也会用到,此插件兼容主流浏览器,IE10以下不支持。
使用方法
载入JavaScript文件
<script src="exif.js"></script>
获取EXIF数据
<script>
EXIF.getData(document.getElementById('imgElement'), function(){//获取图像的数据,能兼容尚未支持提供 EXIF 数据的浏览器获取到元数据。
EXIF.getAllTags(this);//获取图像的全部数据,值以对象的方式返回
EXIF.getTag(this, 'Orientation');//Orientation获取图像的拍摄方向
});
</script>
详细请至中文文档查看:http://code.ciaoca.com/javascript/exif-js/
获取拍摄方向会用到Orientation属性,说明如下:
旋转角度 | 参数值 |
---|---|
0° | 1 |
顺时针90° | 6 |
逆时针90° | 8 |
180° | 3 |
我试了一下,反方向旋转的横拍是0°(1),正常的竖拍是顺时针90°(6),正方向旋转的横拍是180°(3)。
因篇幅有限,Ajax上传过程略过,只做了如下的简单DEMO,仅供参考:
<div class="wrap">
<span class="select_file"></span>
<input type="file" class="file_wrap" accept="image/jpeg,image/jpg,image/png">
<p>
<img id="previewImg" src="images/loading.gif">
</p>
</div>
<script src="script/exif.js"></script>
<script>
{
var doc = document,
button = doc.querySelector('.select_file'),
input = doc.querySelector('.file_wrap'),
previewImg = doc.querySelector('#previewImg'),
Orientation = 1,//拍摄方向默认为1显示正常
upDateFile = ()=>{
var file = input.files[0];
if(!file) return;
var reader = new FileReader();
reader.onload = e=>{
var image = new Image();
image.src = e.target.result;
image.onload = function(){
EXIF.getData(file, function() {
EXIF.getAllTags(this);
Orientation = EXIF.getTag(this, 'Orientation');
//console.log(Orientation);
var imgWidth = image.width,
imgHeight = image.height;
if(imgWidth > imgHeight && imgWidth > 750){
imgWidth = 750;
imgHeight = Math.ceil(750 * image.height / image.width);
}else if(imgWidth < imgHeight && imgHeight > 1334){
imgWidth = Math.ceil(1334 * image.width / image.height);
imgHeight = 1334;
}
var canvas = document.createElement("canvas"),
ctx = canvas.getContext('2d');
canvas.width = imgWidth;
canvas.height = imgHeight;
if(Orientation && Orientation != 1){
switch(Orientation){
case 6:
canvas.width = imgHeight;
canvas.height = imgWidth;
ctx.rotate(Math.PI / 2);
ctx.drawImage(image, 0, -imgHeight, imgWidth, imgHeight);
break;
case 3:
ctx.rotate(Math.PI);
ctx.drawImage(image, -imgWidth, -imgHeight, imgWidth, imgHeight);
break;
case 8:
canvas.width = imgHeight;
canvas.height = imgWidth;
ctx.rotate(3 * Math.PI / 2);
ctx.drawImage(image, -imgWidth, 0, imgWidth, imgHeight);
break;
}
}else{
ctx.drawImage(image, 0, 0, imgWidth, imgHeight);
}
previewImg.src = canvas.toDataURL("image/jpeg",.8);
});
}
};
reader.readAsDataURL(file);
};
button.addEventListener('click',function(event){
doc.querySelector('.file_wrap').click();
},false);
input.addEventListener('change',upDateFile,false);
}
</script>
重点、重点、重点:EXIF.getData必须等待图像完全加载后才可以使用。