vue實現PC端調用攝像頭拍照人臉錄入、移動端調用手機前置攝像頭人臉錄入、及圖片旋轉矯正、壓縮上傳base64格式/文件格式

進入正題

1. PC端調用攝像頭拍照上傳base64格式到後臺,這個沒什麼花裏胡哨的騷操做,直接看代碼 (canvas + video)

<template>
    <div>
        <!--開啓攝像頭-->
        <img @click="callCamera" :src="headImgSrc" alt="攝像頭">
        <!--canvas截取流-->
        <canvas ref="canvas" width="640" height="480"></canvas>
        <!--圖片展現-->
        <video ref="video" width="640" height="480" autoplay></video>
        <!--確認-->
        <el-button size="mini" type="primary" @click="photograph"></el-button>
    </div>
</template>   
<script>
export default {
  data () {
    return {
      headImgSrc: require('@/assets/image/photograph.png')
    }
  },
  methods: {
    // 調用攝像頭
    callCamera () {
      // H5調用電腦攝像頭API
      navigator.mediaDevices.getUserMedia({
        video: true
      }).then(success => {
        // 攝像頭開啓成功
        this.$refs['video'].srcObject = success
        // 實時拍照效果
        this.$refs['video'].play()
      }).catch(error => {
        console.error('攝像頭開啓失敗,請檢查攝像頭是否可用!')
      })
    },
    // 拍照
    photograph () {
      let ctx = this.$refs['canvas'].getContext('2d')
      // 把當前視頻幀內容渲染到canvas上
      ctx.drawImage(this.$refs['video'], 0, 0, 640, 480)
      // 轉base64格式、圖片格式轉換、圖片質量壓縮
      let imgBase64 = this.$refs['canvas'].toDataURL('image/jpeg', 0.7)
      
    // 由字節轉換爲KB 判斷大小
      let str = imgBase64.replace('data:image/jpeg;base64,', '')
      let strLength = str.length
      let fileLength = parseInt(strLength - (strLength / 8) * 2)
    // 圖片尺寸 用於判斷 let size
= (fileLength / 1024).toFixed(2) console.log(size)

    // 上傳拍照信息  調用接口上傳圖片 .........
// 保存到本地 let ADOM = document.createElement('a') ADOM.href = this.headImgSrc ADOM.download = new Date().getTime() + '.jpeg' ADOM.click() }, // 關閉攝像頭 closeCamera () { if (!this.$refs['video'].srcObject) return let stream = this.$refs['video'].srcObject let tracks = stream.getTracks() tracks.forEach(track => { track.stop() }) this.$refs['video'].srcObject = null }, } } </script>

2. 移動端調用手機前置攝像頭人臉錄入、及圖片旋轉矯正、壓縮上傳base64格式/文件流格式;移動端幺蛾子就多了,好比部分手機打開的不是前置攝像頭,部分手機拍照圖片旋轉了,高清手機拍的圖片很是大........

介紹: 1. 經過input 開啓手機前置攝像頭  accept="image/*" 爲開啓攝像頭  capture="user" 爲開啓前置攝像頭 (微信公衆號的話能夠微信jssdk,但它不支持前置攝像頭,默認後置,因此沒用)

    2. 經過 exif.js 判斷旋轉了多少度在經過canvas矯正

            3. 圖片太大或超過規定尺寸則經過canvas壓縮

 HTML 部分:vue

<input ref="file" type="file" accept="image/*" capture="user">

 JS 部分: 接口使用的Vuex調用   可忽略  ajax

  // 壓縮圖片 and 旋轉角度糾正
    compressImage (event) {
      let _this = this
      let file = event.target.files[0]
      let fileReader = new FileReader()
      let img = new Image()
      let imgWidth = ''
      let imgHeight = ''
      // 旋轉角度
      let Orientation = null
      // 縮放圖片須要的canvas
      let canvas = document.createElement('canvas')
      let ctx = canvas.getContext('2d')// 圖片大小  大於2MB 則壓縮
      const isLt2MB = file.size < 2097152
      // 經過 EXIF 獲取旋轉角度 1 爲正常  3 爲 180°  6 順時針90°  9 爲 逆時針90°
      EXIF.getData(file, function () {
        EXIF.getAllTags(this)
        Orientation = EXIF.getTag(this, 'Orientation')
      })
      // 文件讀取 成功執行
      fileReader.onload = function (ev) {
        // 文件base64化,以便獲知圖片原始尺寸
        img.src = ev.target.result
      }
      // 讀取文件
      fileReader.readAsDataURL(file)
      // base64地址圖片加載完畢後
      img.onload = function () {
        imgWidth = img.width
        imgHeight = img.height
        canvas.width = img.width
        canvas.height = img.height
        // 目標尺寸
        let targetWidth = imgWidth
        let targetHeight = imgHeight
        // 不須要壓縮 不須要作旋轉處理
        if (isLt2MB && imgWidth < 960 && imgHeight < 960 && !Orientation) return _this.XMLHttpRequest(file)
        if (isLt2MB && imgWidth < 960 && imgHeight < 960 && +Orientation === 1) return _this.XMLHttpRequest(file)
        // 大於2MB 、img寬高 > 960 則進行壓縮
        if (!isLt2MB || imgWidth >= 960 || imgHeight >= 960) {
          // 最大尺寸
          let maxWidth = 850
          let maxHeight = 850
          // 圖片尺寸超過 960 X 960 的限制
          if (imgWidth > maxWidth || imgHeight > maxHeight) {
            if (imgWidth / imgHeight > maxWidth / maxHeight) {
              // 更寬,按照寬度限定尺寸
              targetWidth = maxWidth
              targetHeight = Math.round(maxWidth * (imgHeight / imgWidth))
            } else {
              targetHeight = maxHeight
              targetWidth = Math.round(maxHeight * (imgWidth / imgHeight))
            }
          }
          // canvas對圖片進行縮放
          canvas.width = targetWidth
          canvas.height = targetHeight
          // 圖片大小超過 2Mb 但未旋轉  則只須要進行圖片壓縮
          if (!Orientation || +Orientation === 1) {
            ctx.drawImage(img, 0, 0, targetWidth, targetHeight)
          }
        }
        // 拍照旋轉 需矯正圖片
        if (Orientation && +Orientation !== 1) {
          switch (+Orientation) {
            case 6:     // 旋轉90度
              canvas.width = targetHeight
              canvas.height = targetWidth
              ctx.rotate(Math.PI / 2)
              // 圖片渲染
              ctx.drawImage(img, 0, -targetHeight, targetWidth, targetHeight)
              break
            case 3:     // 旋轉180度
              ctx.rotate(Math.PI)
              // 圖片渲染
              ctx.drawImage(img, -targetWidth, -targetHeight, targetWidth, targetHeight)
              break
            case 8:     // 旋轉-90度
              canvas.width = targetHeight
              canvas.height = targetWidth
              ctx.rotate(3 * Math.PI / 2)
              // 圖片渲染
              ctx.drawImage(img, -targetWidth, 0, targetWidth, targetHeight)
              break
          }
        }
        // base64 格式   我這是vuex 形式 重點是 canvas.toDataURL('image/jpeg', 1)
        // _this.$store.commit('SAVE_FACE_IMAGE_BASE64', canvas.toDataURL('image/jpeg', 1))
     // 調用接口上傳
// _this.upAppUserFaceByBase64() // 經過文件流格式上傳
     canvas.toBlob(function (blob) { _this.XMLHttpRequest(blob) },
'image/jpeg', 1) } }, // 上傳base64方式 upAppUserFaceByBase64 () { this.$store.dispatch('upAppUserFaceByBase64', { baseFace: this.$store.state.faceImageBase64 }).then(res => { // 上傳成功 }).catch(err => { console.log(err) }) }, // 上傳 XMLHttpRequest (params) { // 圖片ajax上傳
    let action = '後臺接口地址'
let xhr = new XMLHttpRequest()
    let formData = new FormData()
formData.delete('multipartFile') formData.append('multipartFile', params) // 文件上傳成功 xhr.onprogress = this.updateProgress xhr.onerror = this.updateError // 開始上傳 xhr.open('POST', action, true) xhr.send(formData) }, // 上傳成功回調 updateProgress (res) { // res 就是成功後的返回 }, // 上傳失敗回調 updateError (error) { console.log(error) },

結語; 業務代碼刪了致使有點亂了,有不懂或疑問之處歡迎留言;vuex

相關文章
相關標籤/搜索