vue中使用input拍照解決方案

前言

最近在做一個內嵌App的vueH5應用,項目中需要進行拍照上傳人臉識別,然而App不提供原生拍照插件,故想使用H5的拍照。

首先調用H5拍照有兩種方案:

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

這里我們采用第二種方案,第一種兼容性不太好,并且沒有第二種體驗效果好。

代碼實現(xiàn)

拿上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方法中處理系統(tǒng)拿到的圖片,整體的思路就是:先把拿到的file文件去獲取當前文件的角度方向,接著將文件轉為reader對象,在reader的onload函數(shù)中將文件轉為base64,然后把base64傳入resetOrientation 方法中(矯正壓縮圖片),最后再將base64轉為接口所需的blob對象傳給后臺。以下為拍照上傳代碼:

 uploadImg(e) {
        const vm = this;
        let file = e.target.files[0]
        let param = new FormData()  // 創(chuàng)建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對象添加數(shù)據
                //調用接口上傳圖片
                return registerFace(param, config).then((res) => {
                  // 上傳成功邏輯
                })
              });
            });
          }
        });
}

拍照時圖片矯正的問題

由于我的項目中設計到上傳人臉,所以上傳的照片必須是正的,然而在實測中發(fā)現(xiàn),在ios中拍照上傳后會傳一個90° 反轉的照片上去,導致后端無法識別這種照片,在安卓機上則不會。那么,如何解決呢?

思路很簡單,我們在上傳照片前先做判斷:如果是反轉了的照片,我們調整過來,如果不是,不做調整。

1.使用EXIF.js對圖片進行角度判斷;定義一個函數(shù):

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

2.使用canvas drawImage方法將圖片調整正確角度,在回調函數(shù)中使用toDataURL導出調整后的圖片base64對象。

關鍵代碼 base64toBlob函數(shù):

function b64toBlob(b64, onsuccess, onerror) {
    let img = new Image();
    img.onerror = onerror;
    img.onload = function onload() {
      const canvas = document.createElement('canvas');
      canvas.width = img.width;
      canvas.height = img.height;
      let width = img.width;
      let height = img.height;
      let ctx = canvas.getContext('2d');
      let rate = 1;
      ctx.drawImage(img, 0, 0, width, height, 0, 0, width * rate, height * rate);
      canvas.toBlob(onsuccess);
    };
    img.src = b64;
  }

關鍵代碼 resetOrientation函數(shù):

 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;
  };

至此,可解決圖片反轉的問題。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,674評論 1 32
  • 十二班的孩子們: 今天在外學習了一天,但是我的心一半在會場,一半在教室。擔心你們是否又讓韋老師氣得鼻子冒煙,擔心你...
    鹿之言語閱讀 340評論 2 2
  • 《湯與云》 我發(fā)瘋的小戀人請我吃晚飯,透過餐廳開著的窗子,我凝視著上帝用氣體造的活動建筑,不可觸摸之物的絕妙筑。我...
    每日愛圖閱讀 950評論 0 2
  • 我畢業(yè)于師范類院校的師范專業(yè),在以前的認知中,我的就業(yè)方向很明朗,但是又很迷茫,畢業(yè)近三年在一個公司希望通過自己...
    隱形的胖子閱讀 194評論 0 0

友情鏈接更多精彩內容