h5移动端拍照、压缩、上传

作者: MJ 分类: javascript 发布时间: 2019-07-09 15:47

写在前边,现在是三大框架最流行的时候,不用,就好像很落后了的样子,如果您也在用框架(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

欢迎start:
https://github.com/majiang666/h5-camera

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/

欢迎关注小程序,感谢您的支持!

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

邮箱地址不会被公开。 必填项已用*标注