您当前的位置:首页 > 网站建设 > javascript
| php | asp | css | H5 | javascript | Mysql | Dreamweaver | Delphi | 网站维护 | 帝国cms | React | 考试系统 | ajax | jQuery | 小程序 |

Vue调用PC摄像头实现拍照功能

51自学网 2022-02-21 13:40:37
  javascript

本文实例为大家分享了Vue调用PC摄像头实现拍照功能的具体代码,供大家参考,具体内容如下

项目需求:可以本地上传头像,也可以选择拍摄头像上传。

组件:

1、Camera组件:实现 打开、关闭摄像头、绘制、显示图片、用于上传
2、CameraDialog组件:使用ElementUI dialog组件 展示摄像头UI效果
3、外部调用CameraDialog组件,实现拍摄头像上传功能
4、本地上传可使用原生input、也可使用ElementUI upload组件

操作逻辑:

1、新增时将头像图片转为base64调用接口提交,返回url地址用于前端展示
2、替换时,先执行删除操作,在依新增操作执行。
3、本地上传原理跟拍摄上传一致

具体实现方法:

Camera组件

<template>  <div class="camera-box">    <video id="video" :width="videoWidth" :height="videoHeight" v-show="!imgSrc"></video>    <canvas id="canvas" :width="videoWidth" :height="videoHeight" v-show="imgSrc"></canvas>    <p class="camera-p">{{!imgSrc?'提示:请将头像居中按"拍照"键确认':''}}</p>    <el-button type="primary" @click="setImage" v-if="!imgSrc" class="camera-btn">拍照</el-button>    <el-button type="primary" v-if="imgSrc" @click="setFileUpload" class="camera-btn">上传</el-button>  </div></template><script>  import {setFileUpload, deleteFileUpload, addUserCard } from "@/api/houseApi";  export default {    name: 'Camera',    props: {      //【必选】CameraDialog弹窗显示状态      show: {type: Boolean},      //【可选】配合原生input本地上传,用于替换时执行删除      deleteData: {type: Object}    },    data() {      return {        videoWidth: '401',        videoHeight: '340',        thisCancas: null,        thisContext: null,        thisVideo: null,        imgSrc: ``,      }    },    mounted() {      if (this.show) this.getCompetence()    },    methods: {      /*       *@author Brady       *@Time 2019/9/5       *@function  调用权限       *****************************************/      getCompetence() {        var _this = this        this.thisCancas = document.getElementById('canvas')        this.thisContext = this.thisCancas.getContext('2d')        this.thisVideo = document.getElementById('video')        // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象        if (navigator.mediaDevices === undefined) {          navigator.mediaDevices = {}        }        // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象        // 使用getUserMedia,因为它会覆盖现有的属性。        // 这里,如果缺少getUserMedia属性,就添加它。        if (navigator.mediaDevices.getUserMedia === undefined) {          navigator.mediaDevices.getUserMedia = function (constraints) {            // 首先获取现存的getUserMedia(如果存在)            var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia            // 有些浏览器不支持,会返回错误信息            // 保持接口一致            if (!getUserMedia) {              return Promise.reject(new Error('getUserMedia is not implemented in this browser'))            }            // 否则,使用Promise将调用包装到旧的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)        })      },      /*       *@author Brady       *@Time 2019/9/5       *@function  绘制图片       *****************************************/      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        // console.log(_this.imgSrc)        // this.$emit('refreshDataList', this.imgSrc)      },      /*       *@author Brady       *@Time 2019/9/5       *@function  base64转文件       *****************************************/      dataURLtoFile(dataurl, filename) {        var arr = dataurl.split(',')        var mime = arr[0].match(/:(.*?);/)[1]        var bstr = atob(arr[1])        var n = bstr.length        var u8arr = new Uint8Array(n)        while (n--) {          u8arr[n] = bstr.charCodeAt(n)        }        return new File([u8arr], filename, {type: mime})      },      /*       *@author Brady       *@Time 2019/9/5       *@function  关闭摄像头       *****************************************/      stopNavigator() {        this.thisVideo.srcObject.getTracks()[0].stop()      },      //上传图片      setFileUpload() {        //编辑档案-上传人脸照片        if(this.deleteData) {          if (this.deleteData.imagePath) {            deleteFileUpload({id: this.deleteData.id, filePath: this.deleteData.imagePath})              .then(res => {                setFileUpload({image: this.imgSrc})                  .then(res => {                    this.$emit('fileUpload', res.retData.filePath, res.retData.imagePath)                    addUserCard({userId: this.deleteData.userid, cardType: this.deleteData.cardType, userAuditInfo: res.retData.imagePath})                      .then(res => {                        this.$message({message: "上传成功", type: "success"})                      })                      .catch(err => {                        console.log(err)                      })                  })                  .catch(err => {                    console.log(err)                  })              })              .catch(err => {                console.log(err)              })          } else {            setFileUpload({image: this.imgSrc})              .then(res => {                this.$emit('fileUpload', res.retData.filePath, res.retData.imagePath)                addUserCard({userId: this.deleteData.userid, cardType: this.deleteData.cardType, userAuditInfo: res.retData.imagePath})                  .then(res => {                    this.$message({message: "上传成功", type: "success"})                  })                  .catch(err => {                    console.log(err)                  })              })              .catch(err => {                console.log(err)              })          }        } else {          //添加住户-上传人脸照片          setFileUpload({image: this.imgSrc})            .then(res => {              // console.log(res)              this.$message({message: "上传成功", type: "success"})              this.$emit('fileUpload', res.retData.filePath, res.retData.imagePath)            })            .catch(err => {              console.log(err)            })        }      },    },    watch: {      show(val) {        if (val) {          this.imgSrc = ``          this.getCompetence()        } else {          this.stopNavigator()        }      },    }  }</script><style lang="less">  .camera-box {    margin: 0 auto;    text-align: center;    .camera-p {      height: 17px;      line-height: 17px;      font-size: 12px;      font-family: "PingFang SC";      font-weight: 400;      color: rgba(154, 154, 154, 1);      text-align: left;    }    .camera-btn {      margin-top: 20px;    }  }</style>

CameraDialog组件

<template>  <div id="camera-dialog">    <el-dialog            title="拍摄照片"            :visible.sync="dialogVisible"            top="5vh"            width="481px"            @close="dialogCancle"            :close-on-click-modal="false"            :before-close="dialogCancle"    >      <Camera :show="dialogVisible" :deleteData="deleteData" @fileUpload="fileUpload"></Camera>      <span slot="footer" class="dialog-footer">          <!-- <el-button @click="dialogCancle">取 消</el-button> -->        <!-- <el-button type="primary">确 定</el-button> -->        </span>    </el-dialog>  </div></template><script>  import Camera from "@/page/house/Camera.vue"  export default {    name: 'CameraDialog',    props: {      dialogVisible: {type: Boolean},      deleteData: {type: Object}    },    components: {      Camera    },    data() {      return {        filePath: ``,        imagePath: ``,      }    },    methods: {      //关闭弹窗      dialogCancle() {        this.$emit('dialogCancle', false, this.filePath, this.imagePath);      },      //获取人脸照片地址      fileUpload(filePath, imagePath) {        this.filePath = filePath        this.imagePath = imagePath        this.dialogCancle()      }    }  }</script><style scoped></style>

外部调用组件

<template>  <div>    <div class="form-thumb">     <img :src="filePath" alt="">      <i class="delete-btn" @click="deleteUploadFile" v-if="deleteData.imagePath">x</i>    </div>    <div class="upload-btn">       <input type="file" name="userAuditInfo" id="userAuditInfo" @change="getUploadFile" ref="inputFile">       <el-button type="defualt" size="small" @click="localUploadFile">本地上传</el-button>       <el-button type="default" size="small" @click="dialogVisible=true">拍摄照片</el-button>     </div>    <!-- 拍摄照片弹窗 -->    <CameraDialog :dialogVisible="dialogVisible" @dialogCancle="dialogCancleCamera" :deleteData="deleteData" />  </div> </template><script>  import CameraDialog from "./CameraDialog.vue"  import { setFileUpload, deleteFileUpload, addUserCard } from "@/api/houseApi.js"  export default {    data() {      return {        filePath: require('@/assets/images/null.png'), //身份证头像        dialogVisible: false,        //操作删除人脸照片相关字段        deleteData: {          userid: this.$route.query.userId,          id: ``,          cardType: 4,          imagePath: ``,        }   } }, methods: {      //模拟点击本地上传人脸照片      localUploadFile() {        this.$refs.inputFile.click()      },      //本地上传人脸照片      getUploadFile() {        let input = document.getElementById('userAuditInfo')        let file = input.files[0]        this.getBase64(file)          .then(res => {            if (this.deleteData.imagePath) {              deleteFileUpload({id: this.deleteData.id, filePath: this.deleteData.imagePath})                .then(() => {                  this.setFileUpload(res)                })            } else {              this.setFileUpload(res)            }          })          .catch(err => {            console.log(err)          })      },      //上传人脸照片      setFileUpload(res) {        setFileUpload({image: res})          .then(res => {            this.filePath = res.retData.filePath            this.deleteData.imagePath = res.retData.imagePath            addUserCard({userId: this.deleteData.userid, cardType: this.deleteData.cardType, userAuditInfo: res.retData.imagePath})              .then(res => {                this.$message({message: res.retInfo, type: "success"})                //用于更新数据,此方法未展示                this.getInfo()              })              .catch(err => {                console.log(err)              })          })          .catch(err => {            console.log(err)          })      },      //转base64      getBase64(file) {        return new Promise(function (resolve, reject) {          let reader = new FileReader();          let imgResult = "";          reader.readAsDataURL(file);          reader.onload = function () {            imgResult = reader.result;          };          reader.onerror = function (error) {            reject(error);          };          reader.onloadend = function () {            resolve(imgResult);          };        });      },      //删除人脸照片      deleteUploadFile() {        this.$confirm(`确认删除?`, '提示', {          confirmButtonText: '确定',          cancelButtonText: '取消',          type: 'warning'        }).then(() => {          deleteFileUpload({id: this.deleteData.id, filePath: this.deleteData.imagePath})            .then(res => {              this.$message({message: res.retInfo, type: "success"})              this.filePath = require('@/assets/images/null.png')              this.deleteData.imagePath = ''            })            .catch(err => {              console.log(err)            })        }).catch(() => {});      },      //Dialog弹窗取消、获取上传人脸照片      dialogCancleCamera(str, filePath, imagePath) {        this.dialogVisible = str        // this.houseInfo.filePath = filePath        // this.houseInfo.userAuditInfo = imagePath        this.filePath = filePath        this.deleteData.imagePath = imagePath        this.getInfo()      },  }  }</script> <style scoped="scoped">  .upload-btn {    position: relative;    margin: 20px 12px 0 0;    text-align: right;  }  input#userAuditInfo {    position: absolute;    display: inline-block;    width: 80px;    height: 32px;    top: 0;    cursor: pointer;    font-size: 0;    z-index: -1;    /*opacity: 0;*/  }  .delete-btn {    position: absolute;    top: -6px;    right: -6px;    display: inline-block;    width: 16px;    height: 16px;    line-height: 14px;    background: rgba(251, 135, 66, 1);    border-radius: 8px;    text-align: center;    font-size: 12px;    color: #fff;    cursor: pointer;  }</style>

以上只作为实现参考,具体操作依实际需求做相应调整。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持51zixue.net。


下载地址:
vue实现调取手机摄像头和相册功能
Vue使用video标签实现视频播放
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。