纵横研究院VU...

vue中使用input拍照解决方案

2019-05-08  本文已影响33人  月满轩尼诗_

前言

最近在做一个内嵌App的vueH5应用,项目中需要进行拍照上传人脸识别,然而App不提供原生拍照插件,故想使用H5的拍照。

首先调用H5拍照有两种方案:

1.使用H5Api:navigator.getUserMedia(constraints, successCallback, errorCallback);
2.使用input type=file 。

这里我们采用第二种方案,第一种兼容性不太好,并且没有第二种体验效果好。

代码实现

拿上input标签:

 <input type="file" name="photo" accept=".jpg,.png" multiple>

默认样式比较丑,我们需要美化样式:

HTML:

       <div class="face">
          <input type="file" name="file" class="upload" @change="uploadImg">
          <span class="span-txt">开始认证</span>
        </div>

CSS:

 .face{
        margin-top: 20px;
        position: relative;
        .upload{
          width: calc(100% - 40px);
          height: 43px;
          line-height: 43px;
          opacity: 0;
          position: absolute;
          z-index: 22;
          left: 0;
          margin: auto;
          right: 0;
        }
        .span-txt{
          font-family: PingFangSC-Medium;
          font-size: 16px;
          color: #FFFFFF;
          position: absolute;
          left: 0;
          margin: auto;
          right: 0;
          background: #CDAB6A;
          width: calc(100% - 40px);
          height: 43px;
          line-height: 43px;
          border-radius: 4px;
          text-align: center;
        }
      }

美化后效果:


image.png

如同button一般,点击即可调用摄像头拍照,或者使用相册。
接下来就是使用处理图片进行上传
在uploadImg方法中处理系统拿到的图片,整体的思路就是:先把拿到的file文件去获取当前文件的角度方向,接着将文件转为reader对象,在reader的onload函数中将文件转为base64,然后把base64传入resetOrientation 方法中(矫正压缩图片),最后再将base64转为接口所需的blob对象传给后台。以下为拍照上传代码:

 uploadImg(e) {
        const vm = this;
        let file = e.target.files[0]
        let param = new FormData()  // 创建form对象
        let config = {
          headers: {'Content-Type': 'multipart/form-data'}
        }
      //解决ios拍照照片自动旋转问题
      getOrientation(file, function (orientation) {
          const reader = new FileReader();
          reader.readAsDataURL(file);
          reader.onload = function(evt){
            const base64 = evt.target.result;
            // 将图片旋转到正确的角度 并压缩
            resetOrientation(base64, orientation, function (resultBase64) {
              b64toBlob(resultBase64, function (blob) {
                param.append('file', blob); // 通过append向form对象添加数据
                //调用接口上传图片
                return registerFace(param, config).then((res) => {
                  // 上传成功逻辑
                })
              });
            });
          }
        });
}

拍照时图片矫正的问题

由于我的项目中设计到上传人脸,所以上传的照片必须是正的,然而在实测中发现,在ios中拍照上传后会传一个90° 反转的照片上去,导致后端无法识别这种照片,在安卓机上则不会。那么,如何解决呢?

思路很简单,我们在上传照片前先做判断:如果是反转了的照片,我们调整过来,如果不是,不做调整。

1.使用EXIF.js对图片进行角度判断;定义一个函数:

  //  获取图片的角度
  function getOrientation(file, callback) {
    EXIF.getData(file, function () {
      var orientation = EXIF.getTag(this, 'Orientation');
      return callback(orientation);
    });
  }

2.使用canvas drawImage方法将图片调整正确角度,在回调函数中使用toDataURL导出调整后的图片base64对象。

关键代码 resetOrientation函数:

 function resetOrientation(srcBase64, srcOrientation, callback) {
    const img = new Image();
    img.onload = function () {
      const width = img.width,
        height = img.height,
        canvas = document.createElement('canvas'),
        ctx = canvas.getContext('2d');
      // 判断图片尺寸压缩一定比率
      const big = (img.width > img.height) ? img.width : img.height;
      let rate = 1;
      if (big > 840) {
        rate = 840 / big;
      }
      canvas.width = width * rate;
      canvas.height = height * rate;
      // 安卓机不需要矫正图片
      if(srcOrientation && srcOrientation !== 1){
     // 判断图片方向,压缩并矫正
        switch (srcOrientation) {
        // 当图片旋转180°时
          case 3:
            ctx.rotate(Math.PI);
            ctx.drawImage(this, -this.width * rate, -this.height * rate, this.width * rate, this.height * rate);
            break;
       // 当图片旋转90°时
          case 6:
            canvas.width = this.height * rate;
            canvas.height = this.width * rate;
            ctx.rotate(Math.PI / 2);
            // (0,-imgHeight) 从旋转原理图那里获得的起始点
            ctx.drawImage(this, 0, -this.height * rate, this.width * rate, this.height * rate);
            break;
       // 当图片旋转270°时
          case 8:
            canvas.width = this.height * rate;
            canvas.height = this.width * rate;
            ctx.rotate(3 * Math.PI / 2);
            ctx.drawImage(this, -this.width * rate, 0, this.width * rate, this.height * rate);
            break;
          default:
            ctx.drawImage(img, 0, 0, width, height, 0, 0, width * rate, height * rate);
        }
      }else {
        ctx.drawImage(img, 0, 0, width, height, 0, 0, width * rate, height * rate);
      }
      // 返回 base64
      callback(canvas.toDataURL('image/jpeg'));
    };
    img.src = srcBase64;
  };

至此,可解决图片反转的问题。

上一篇下一篇

猜你喜欢

热点阅读