欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue如何調(diào)用攝像頭實現(xiàn)拍照上傳圖片、本地上傳圖片

 更新時間:2023年07月27日 16:08:19   作者:Liux-  
這篇文章主要給大家介紹了關(guān)于vue如何調(diào)用攝像頭實現(xiàn)拍照上傳圖片、本地上傳圖片的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

今天項目上遇到一個功能,人臉錄入,要求用戶可以自己調(diào)用攝像頭拍照上傳圖片,還可以上傳本地圖片,這個功能并沒有那么復(fù)雜,今天就封裝一下這個功能,首先咱們看一下效果。

下面是封裝好的效果,因為封裝的時候做了頁面銷毀關(guān)閉攝像頭,所以加了一個打開攝像頭的功能,我們可以自己拍照,也有本地上傳按鈕

下面是拍照效果,左邊部分是你點擊拍照上傳服務(wù)器返回來的地址,然后顯示效果,右邊就是咱們上面說的封裝好的組件

下面看一下組件實現(xiàn)的代碼

主要功能邏輯就是調(diào)用是攝像頭權(quán)限,把實時畫面顯示到video里面,點擊拍照的時候繪制vanvas,然后把canvas轉(zhuǎn)base64圖片,base64圖片轉(zhuǎn)文件進行上傳,上傳圖片就不多介紹了,就是Element文件上傳,配置action,headers 就行。下面直接上代碼吧。

<template>
  <div class="camera_outer">
    <video id="videoCamera" :width="videoWidth" :height="videoHeight" autoplay></video>
    <canvas id="canvasCamera" style="display:none;" :width="videoWidth" :height="videoHeight"></canvas>
    <div style="display: flex;justify-content: space-between;align-items: center;">
      <el-button type="primary" @click="setImage()">拍照</el-button>
      <el-upload style="display: flex;align-items: center;" :headers="headers" :show-file-list="false"
        :on-success="handleAvatarSuccess" class="avatar-uploader" action="/admin/sys-file/upload">
        <el-button type="primary">上傳照片</el-button>
      </el-upload>
      <el-button @click="getCompetence()">打開攝像頭</el-button>
    </div>
  </div>
</template>
<script>
import store from '@/store'
import { uploadImg } from '@/api/visitinfo'
export default {
  data() {
    return {
      videoWidth: 300,
      videoHeight: 300,
      imgSrc: '',
      thisCancas: null,
      thisContext: null,
      thisVideo: null,
      headers: {
        Authorization: 'Bearer ' + store.getters.access_token
      }
    }
  },
  mounted() {
    this.getCompetence()
  },
  destroyed() {
    this.stopNavigator()
  },
  methods: {
    handleAvatarSuccess(res, file) {
      this.$emit('refreshDataList', res.data.url)
    },
    // 調(diào)用權(quán)限(打開攝像頭功能)
    getCompetence() {
      var _this = this
      this.thisCancas = document.getElementById('canvasCamera')
      this.thisContext = this.thisCancas.getContext('2d')
      this.thisVideo = document.getElementById('videoCamera')
      // 舊版本瀏覽器可能根本不支持mediaDevices,我們首先設(shè)置一個空對象
      if (navigator.mediaDevices === undefined) {
        navigator.mediaDevices = {}
      }
      // 一些瀏覽器實現(xiàn)了部分mediaDevices,我們不能只分配一個對象
      // 使用getUserMedia,因為它會覆蓋現(xiàn)有的屬性。
      // 這里,如果缺少getUserMedia屬性,就添加它。
      if (navigator.mediaDevices.getUserMedia === undefined) {
        navigator.mediaDevices.getUserMedia = function (constraints) {
          // 首先獲取現(xiàn)存的getUserMedia(如果存在)
          var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia
          // 有些瀏覽器不支持,會返回錯誤信息
          // 保持接口一致
          if (!getUserMedia) {
            return Promise.reject(new Error('getUserMedia is not implemented in this browser'))
          }
          // 否則,使用Promise將調(diào)用包裝到舊的navigator.getUserMedia
          return new Promise(function (resolve, reject) {
            getUserMedia.call(navigator, constraints, resolve, reject)
          })
        }
      }
      var constraints = { audio: false, video: { width: this.videoWidth, height: this.videoHeight, transform: 'scaleX(-1)' } }
      navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
        // 舊的瀏覽器可能沒有srcObject
        if ('srcObject' in _this.thisVideo) {
          _this.thisVideo.srcObject = stream
        } else {
          // 避免在新的瀏覽器中使用它,因為它正在被棄用。
          _this.thisVideo.src = window.URL.createObjectURL(stream)
        }
        _this.thisVideo.onloadedmetadata = function (e) {
          _this.thisVideo.play()
        }
      }).catch(err => {
        console.log(err)
      })
    },
    //  繪制圖片(拍照功能)
    setImage() {
      var _this = this
      // 點擊,canvas畫圖
      _this.thisContext.drawImage(_this.thisVideo, 0, 0, _this.videoWidth, _this.videoHeight)
      // 獲取圖片base64鏈接
      var image = this.thisCancas.toDataURL('image/png')
      _this.imgSrc = image
      const file = image
      const time = (new Date()).valueOf()
      const name = time + '.png'
      const conversions = this.base64ToFile(file, name)
      const data = new FormData()
      data.append('file', conversions)
      uploadImg(data).then(res => {
        if (res.data.code == 0) {
          this.$emit('refreshDataList', res.data.data.url)
        }
      })
    },
    // base64圖片轉(zhuǎn)file的方法(base64圖片, 設(shè)置生成file的文件名)
    base64ToFile(base64, fileName) {
      // 將base64按照 , 進行分割 將前綴  與后續(xù)內(nèi)容分隔開
      const data = base64.split(',')
      // 利用正則表達式 從前綴中獲取圖片的類型信息(image/png、image/jpeg、image/webp等)
      const type = data[0].match(/:(.*?);/)[1]
      // 從圖片的類型信息中 獲取具體的文件格式后綴(png、jpeg、webp)
      const suffix = type.split('/')[1]
      // 使用atob()對base64數(shù)據(jù)進行解碼  結(jié)果是一個文件數(shù)據(jù)流 以字符串的格式輸出
      const bstr = window.atob(data[1])
      // 獲取解碼結(jié)果字符串的長度
      let n = bstr.length
      // 根據(jù)解碼結(jié)果字符串的長度創(chuàng)建一個等長的整形數(shù)字數(shù)組
      // 但在創(chuàng)建時 所有元素初始值都為 0
      const u8arr = new Uint8Array(n)
      // 將整形數(shù)組的每個元素填充為解碼結(jié)果字符串對應(yīng)位置字符的UTF-16 編碼單元
      while (n--) {
        // charCodeAt():獲取給定索引處字符對應(yīng)的 UTF-16 代碼單元
        u8arr[n] = bstr.charCodeAt(n)
      }
      // 利用構(gòu)造函數(shù)創(chuàng)建File文件對象
      // new File(bits, name, options)
      const file = new File([u8arr], `${fileName}.${suffix}`, {
        type: type
      })
      // 將File文件對象返回給方法的調(diào)用者
      return file
    },
    // 關(guān)閉攝像頭
    stopNavigator() {
      this.thisVideo.srcObject.getTracks()[0].stop()
    }
  }
}
</script>
<style lang="less" scoped>
.camera_outer {
  position: relative;
  overflow: hidden;
  // background: url("../../assets/img/user_0608_04.png") no-repeat center;
  background-size: 100%;
  video,
  canvas,
  .tx_img {
    -moz-transform: scaleX(-1);
    -webkit-transform: scaleX(-1);
    -o-transform: scaleX(-1);
    transform: scaleX(-1);
  }
  .btn_camera {
    position: absolute;
    bottom: 4px;
    left: 0;
    right: 0;
    height: 50px;
    background-color: rgba(0, 0, 0, 0.3);
    line-height: 50px;
    text-align: center;
    color: #ffffff;
  }
  .bg_r_img {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    top: 0;
  }
  .img_bg_camera {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    top: 0;
    img {
      width: 300px;
      height: 300px;
    }
    .img_btn_camera {
      position: absolute;
      bottom: 0;
      left: 0;
      right: 0;
      height: 50px;
      line-height: 50px;
      text-align: center;
      background-color: rgba(0, 0, 0, 0.3);
      color: #ffffff;
      .loding_img {
        width: 50px;
        height: 50px;
      }
    }
  }
}
</style>

封裝好以后就是調(diào)用了

<template>
  <div>
       <TakePhotos ref="TakePhotos" @refreshDataList="refreshDataList" />  
  </div>
</template>
<script>
export default {
  methods: {
    refreshDataList(imgSrc) {
    // 這里返回服務(wù)器圖片的地址
      console.log(imgSrc)
    },
}
</script>

上面代碼注釋已經(jīng)都寫了,相信大家都能看懂

總結(jié)

到此這篇關(guān)于vue如何調(diào)用攝像頭實現(xiàn)拍照上傳圖片、本地上傳圖片的文章就介紹到這了,更多相關(guān)vue調(diào)用攝像頭拍照上傳圖片內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue2和vue3子組件父組件之間的傳值方法

    vue2和vue3子組件父組件之間的傳值方法

    在組件化開發(fā)的過程中難免會遇見子組件和父組件之間的通訊那么這里講關(guān)于vue2和vue3不同的通訊方式,文中有詳細的代碼示例供大家參考,感興趣的同學(xué)可以閱讀下
    2023-05-05
  • ant-design-vue動態(tài)表格合并案例

    ant-design-vue動態(tài)表格合并案例

    這篇文章主要介紹了ant-design-vue動態(tài)表格合并案例,文章圍繞主題通過案例詳解展開相關(guān)內(nèi)容,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • Vue.js 點擊按鈕顯示/隱藏內(nèi)容的實例代碼

    Vue.js 點擊按鈕顯示/隱藏內(nèi)容的實例代碼

    下面小編就為大家分享一篇Vue.js 點擊按鈕顯示/隱藏內(nèi)容的實例代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • vue實現(xiàn)前臺列表數(shù)據(jù)過濾搜索、分頁效果

    vue實現(xiàn)前臺列表數(shù)據(jù)過濾搜索、分頁效果

    這篇文章主要為大家詳細介紹了vue實現(xiàn)前臺列表數(shù)據(jù)過濾搜索、分頁效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • 基于mpvue的小程序項目搭建的步驟

    基于mpvue的小程序項目搭建的步驟

    mpvue 是美團開源的一套語法與vue.js一致的、快速開發(fā)小程序的前端框架,這篇文章主要介紹了基于mpvue的小程序項目搭建的步驟,非常具有實用價值,需要的朋友可以參考下
    2018-05-05
  • vue2之jessibuca視頻插件使用教程詳細講解

    vue2之jessibuca視頻插件使用教程詳細講解

    Jessibuca進行直播流播放,為用戶帶來便捷、高效的視頻觀看體驗,下面這篇文章主要給大家介紹了關(guān)于vue2之jessibuca視頻插件使用的相關(guān)資料,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2024-09-09
  • Vue.js中使用道具方法demo

    Vue.js中使用道具方法demo

    這篇文章主要為大家介紹了Vue.js中使用道具方法demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • Vue報錯:TypeError:?Cannot?create?property?‘xxxx‘?on的解決

    Vue報錯:TypeError:?Cannot?create?property?‘xxxx‘?on的解決

    這篇文章主要介紹了Vue報錯:TypeError:?Cannot?create?property?‘xxxx‘?on的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Vue實現(xiàn)todo應(yīng)用的示例

    Vue實現(xiàn)todo應(yīng)用的示例

    這篇文章主要介紹了Vue實現(xiàn)todo應(yīng)用的示例,幫助大家更好的理解和學(xué)習(xí)使用vue框架,感興趣的朋友可以了解下
    2021-02-02
  • vue如何解決sass-loader的版本過高導(dǎo)致的編譯錯誤

    vue如何解決sass-loader的版本過高導(dǎo)致的編譯錯誤

    這篇文章主要介紹了vue如何解決sass-loader的版本過高導(dǎo)致的編譯錯誤問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06

最新評論