H5移动端调用摄像头拍照、压缩上传图片

这周产品提出了新的需求,要求前端H5页面调起移动设备摄像头,并实现拍照功能。完成之后来记录一下开发经历,希望对之后遇到同样问题开发者有所帮助!

首先H5要调起设备摄像头需要使用 input 标签,借助标签的 capture 属性来完成调起操作。上代码:


     

    

    

拍照完成之后,需要读取文件,这就需要使用 FileReader 对象来完成相应操作。上代码:

// 创建 FileReader 对象
var reader = new FileReader();
    reader.onload = function() {
        that.compress(this.result, file);
    };
reader.readAsDataURL(file);
this.fileUrl = window.URL.createObjectURL(file);

// this.result 既是读取文件结果,是一个Base64形式的文件流,类似data:image/png;base64,*****
// file 是获去到的文件对象
file.png

that.compress 这个方法是用来处理图片压缩,是否旋转等功能。
this.fileUrl 是用来做 选定照片 / 拍摄照片 回显,就是 img 的 src 属性值。

到这里就可以实现简单的H5调起相册、摄像头操作。但是测试的时候会发现像素好的手机拍出来的照片非常大,就造成了上传接口相应超时问题,此时不要慌,接下来就说一说关于照片压缩问题。

这里的图片压缩就需要 canvas 来配合实现。

        let that = this;
        var width, height;
        var MAX_WH = 800;
        var image = new Image();

        image.onload = function() {
          if (image.height > MAX_WH) {
            // 宽度等比例缩放 *=
            image.width *= MAX_WH / image.height;
            image.height = MAX_WH;
          }
          if (image.width > MAX_WH) {
            // 宽度等比例缩放 *=
            image.height *= MAX_WH / image.width;
            image.width = MAX_WH;
          }
          //压缩
          var quality = 80;
          var cvs = document.createElement("canvas");
          var context = cvs.getContext("2d");
          cvs.width = width = image.width;
          cvs.height = height = image.height;

          switch (orientation) {
            case 6:
            case 8:
              cvs.width = height;
              cvs.height = width;
              break;
          }
          context.clearRect(0, 0, cvs.width, cvs.height);
          context.drawImage(image, 0, 0, image.width, image.height);
          that.readerResult = cvs.toDataURL("image/jpeg", quality / 100);
          that.getBankcardFn(); // 调用上传接口
        };
        image.src = res;

首先,创建Image对象,给imagesrc属性赋值加载完之后,调用onload。在onload中进行图片的压缩操作。
cvs.toDataURL() 方法返回的就是压缩之后的图片的 Base64 编码,这时候就可以把编码上传至服务器了。

到了这里已经就完成了一大半,功能已经基本实现,现在就可以开始考虑优化、提高用户体验了。经过测试,会发现iOS部分机型会莫名造成图片旋转,不要慌。

这里搭配EXIF对象来拿到图片的原信息。

      var orientation = 0;
      EXIF.getData(file, function() {
          orientation = EXIF.getTag(file, "Orientation");
      });
        //解决ios图片旋转问题
        switch (orientation) {
          //iphone横屏拍摄,此时home键在左侧
          case 3:
            // 180度向左旋转
            context.translate(width, height);
            context.rotate(Math.PI);
            break;
          //iphone竖屏拍摄,此时home键在下方(正常拿手机的方向)
          case 6:
             context.rotate(0.5 * Math.PI);
            context.translate(0, -height);
            break;
          //iphone竖屏拍摄,此时home键在上方
          case 8:
            // 逆时针旋转90度
            context.rotate(-0.5 * Math.PI);
             context.translate(-width, 0);
            break;
        }

这里的EXIF对象是(Exchangeable Image File)是“可交换图像文件”的缩写,当中包含了专门为数码相机的照片而定制的元数据,可以记录数码照片的拍摄参数、缩略图及其他属性信息,简单来说,Exif信息是镶嵌在 JPEG/TIFF 图像文件格式内的一组拍摄参数,需要注意的是EXIF信息是不支持png,webp等图片格式的。
可以引入CDN 也可以 npm install exif-js --save

到了这里功能就可以交付了。下面附上完整代码粘贴即用:








你可能感兴趣的:(H5移动端调用摄像头拍照、压缩上传图片)