h5移动端拍照、压缩、上传
写在前边,现在是三大框架最流行的时候,不用,就好像很落后了的样子,如果您也在用框架(vue\react\angular ),并且用到了h5拍照功能,那么我推荐您直接忽略本文,直接去用下边两个推荐模块(我自己在用fork过来的ImageFile感谢原作者),都已经封装的很方便了,包括我们会遇到的压缩、照片旋转等问题,拿来直接用即可。
https://github.com/eJayYoung/vux-uploader-component
https://github.com/majiang666/ImageFile
今天所写的不是基于最新的框架,因为上边的项目用到了很多es6的新特性,目前所在的项目比较老,就自己动手封装一下能用在老项目,顺便也学习一下原理,总之这次收获还是很大的,虽然也不是从0开始的。
首先需要知道的特殊知识点(js、css、html必备):canvas(创建和图片、旋转)、 new FileReader() 、 toDataURL ()、Exif.js
demo: https://www.sjooy.com/h5-camera/index.html
先说一下解题思路(只是片段代码,建议去看源码更清晰):
创建input —-> 获取files —-> 压缩图片 —-> 特殊机型图片旋转 —-> 转base64 —-> 预览
一:首先创建input
html:
<div>
<img src="../../../img/gift/data.png" />
<input type="file" accept="image/*" class="img-upload">
</div>
css:
div{
position:relative;
}
input{
width:100%;
height:100%;
position: absolute;
top:0;
left:0;
opacity: 0;
}
二:获取files
$(".img-upload").change(function () {
imgUpload.readURL(this);
});
imgUpload.readURL = function (input) {
console.log("loading start")
var _this = this;
if (input.files && input.files[0]) {
this.getOrientation(input.files[0], function(orientation) {
var reader = new FileReader();
var fileSize = Math.round(input.files[0].size / 1024 / 1024) ; //以M为单位(把字节转换为M)
//input.files[0] 该信息包含:图片的大小,以byte计算 获取size的方法如下:input.files[0].size;
reader.onload = function (e) {
//调用图片压缩方法:compress();
_this.compress(e.target.result,fileSize,input,orientation);
};
reader.readAsDataURL(input.files[0]);
});
}
}
三:压缩图片
var dataUrl = canvas.toDataURL( 'image/png', compressRate);
imgUpload.getCompressRate = function (allowMaxSize,fileSize){
var compressRate = 1;
if(fileSize / allowMaxSize > 4){
compressRate = 0.5;
} else if(fileSize / allowMaxSize >3){
compressRate = 0.6;
} else if(fileSize / allowMaxSize >2){
compressRate = 0.7;
} else if(fileSize > allowMaxSize){
compressRate = 0.8;
} else{
compressRate = 0.9;
}
return compressRate;
}
四:特殊机型图片旋转
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;
default: //正常值
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
}
五:canvas转base64
canvas.toDataURL( 'image/png', compressRate);
六:预览
obj.previousElementSibling.setAttribute('src',dataUrl);
本文实现参考:
https://my.oschina.net/zyxchuxin/blog/700381
https://juejin.im/post/5baf4a04e51d450ea52fd9a4#heading-0
https://github.com/majiang666/ImageFile/blob/master/src/index.js
http://code.ciaoca.com/javascript/exif-js/
欢迎关注小程序,感谢您的支持!