美文网首页纵横研究院VU...
vue中使用input拍照解决方案

vue中使用input拍照解决方案

作者: 月满轩尼诗_ | 来源:发表于2019-05-08 22: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;
      };
    

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

    相关文章

      网友评论

        本文标题:vue中使用input拍照解决方案

        本文链接:https://www.haomeiwen.com/subject/pvcvoqtx.html