Vue calls the PC camera to realize the photo function

Vue calls the PC camera to realize the photo function

This article example shares the specific code of Vue calling the PC camera to realize the photo function for your reference. The specific content is as follows

Project requirements: You can upload the avatar locally, or you can choose to take a photo and upload it.

Components:

1. Camera component: realize opening and closing the camera, drawing, displaying pictures, and uploading
2. CameraDialog component: Use ElementUI dialog component to display camera UI effect
3. Call the CameraDialog component externally to realize the function of uploading the portrait
4. Local upload can use native input or ElementUI upload component

Operation logic:

1. When adding, convert the avatar image to base64 and submit it to the calling interface, and return the URL address for front-end display
2. When replacing, first perform the delete operation, and then perform the add operation.
3. The principle of local upload is the same as that of shooting upload

Specific implementation method:

Camera Component

<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?'Tip: Please center the avatar and press the "photo" button to confirm':''}}</p>
    <el-button type="primary" @click="setImage" v-if="!imgSrc" class="camera-btn">Take a photo</el-button>
    <el-button type="primary" v-if="imgSrc" @click="setFileUpload" class="camera-btn">Upload</el-button>
  </div>
</template>

<script>
  import {setFileUpload, deleteFileUpload, addUserCard } from "@/api/houseApi";

  export default {
    name: 'Camera',
    props: {
      //【Required】CameraDialog pop-up window display status show: {type: Boolean},
      //[Optional] Use native input for local upload to delete when replacing 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 calling permission*********************************************/
      getCompetence() {
        var _this = this
        this.thisCancas = document.getElementById('canvas')
        this.thisContext = this.thisCancas.getContext('2d')
        this.thisVideo = document.getElementById('video')
        // Older browsers may not support mediaDevices at all, so we first set an empty object if (navigator.mediaDevices === undefined) {
          navigator.mediaDevices = {}
        }
        // Some browsers implement partial mediaDevices, and we can't just assign an object // using getUserMedia because it will overwrite existing properties.
        // Here, if the getUserMedia property is missing, add it.
        if (navigator.mediaDevices.getUserMedia === undefined) {
          navigator.mediaDevices.getUserMedia = function (constraints) {
            // First get the existing getUserMedia (if it exists)
            var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia
            // Some browsers do not support it and will return an error message // Keep the interface consistent if (!getUserMedia) {
              return Promise.reject(new Error('getUserMedia is not implemented in this browser'))
            }
            // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
            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) {
          // Old browsers may not have srcObject
          if ('srcObject' in _this.thisVideo) {
            _this.thisVideo.srcObject = stream
          } else {
            // Avoid using this in newer browsers as it is being deprecated.
            _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 draw picture*********************************************/
      setImage() {
        var _this = this
        // Click, canvas drawing_this.thisContext.drawImage(_this.thisVideo, 0, 0, _this.videoWidth, _this.videoHeight)
        // Get the base64 link of the image 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 convert file********************************************/
      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 Close the camera*********************************************/
      stopNavigator() {
        this.thisVideo.srcObject.getTracks()[0].stop()
      },
      //Upload picture setFileUpload() {
        //Edit file - upload face photo 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: "Upload successful", 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: "Upload successful", type: "success"})
                  })
                  .catch(err => {
                    console.log(err)
                  })
              })
              .catch(err => {
                console.log(err)
              })
          }
        } else {
          //Add resident - upload face photo setFileUpload({image: this.imgSrc})
            .then(res => {
              // console.log(res)
              this.$message({message: "Upload successful", 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 Component

<template>
  <div id="camera-dialog">
    <el-dialog
            title="Take a photo"
            :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">Cancel</el-button> -->
        <!-- <el-button type="primary">OK</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: {
      //Close the pop-up window dialogCancle() {
        this.$emit('dialogCancle', false, this.filePath, this.imagePath);
      },
      //Get the address of the face photo fileUpload(filePath, imagePath) {
        this.filePath = filePath
        this.imagePath = imagePath
        this.dialogCancle()
      }
    }
  }
</script>

<style scoped>
</style>

External call component

<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">Local upload</el-button>
       <el-button type="default" size="small" @click="dialogVisible=true">Take a photo</el-button>
     </div>
    <!-- Pop-up window for taking photos-->
    <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'), //ID card avatar dialogVisible: false,
        //Operation to delete face photo related fields deleteData: {
          userid: this.$route.query.userId,
          id: ``,
          cardType: 4,
          imagePath: ``,
        }
   }
 },
 methods: {
      //Simulate clicking to upload a face photo locallylocalUploadFile() {
        this.$refs.inputFile.click()
      },
      //Local upload face photo 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)
          })
      },
      //Upload face photo 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"})
                //Used to update data, this method does not show this.getInfo()
              })
              .catch(err => {
                console.log(err)
              })
          })
          .catch(err => {
            console.log(err)
          })
      },
      //Convert to 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);
          };
        });
      },
      //Delete face photo deleteUploadFile() {
        this.$confirm(`Confirm deletion?`, 'prompt', {
          confirmButtonText: 'Confirm',
          cancelButtonText: 'Cancel',
          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(() => {});
      },
      //Cancel the Dialog pop-up window and get the uploaded face photo 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>

The above is only for reference. The specific operations should be adjusted according to actual needs.

The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM.

You may also be interested in:
  • Vue implements calling PC camera to take photos in real time
  • Vue calls the computer camera to realize the photo function
  • Vue calls the local camera to realize the photo function
  • Vue2.0 implements the function of calling the camera to take pictures, and exif.js implements the picture upload function
  • Vue calls the camera to take pictures and save them locally

<<:  Modify the default data directory of MySQL 8.0 (quick operation without configuration)

>>:  Solution to the 404/503 problem when logging in to TeamCenter12

Recommend

Linux touch command usage examples

Detailed explanation of linux touch command: 1. C...

How to draw a vertical line between two div tags in HTML

Recently, when I was drawing an interface, I enco...

Vue.js Textbox with Dropdown component

A Textbox with Dropdown allows users to select an...

How to publish static resources in nginx

step Place the prepared static resource files in ...

How to remove the blue box that appears when the image is used as a hyperlink

I recently used Dreamweaver to make a product pres...

Detailed explanation of the use of default in MySQL

NULL and NOT NULL modifiers, DEFAULT modifier, AU...

Method to detect whether ip and port are connectable

Windows cmd telnet format: telnet ip port case: t...

Gallery function implemented by native Js

Table of contents The first The second Native Js ...

Detailed explanation of JS homology strategy and CSRF

Table of contents Overview Same Origin Policy (SO...

Detailed example of using js fetch asynchronous request

Table of contents Understanding Asynchrony fetch(...

Which loop is the fastest in JavaScript?

Knowing which for loop or iterator is right for o...

Detailed explanation of CSS3+JS perfect implementation of magnifying glass mode

About a year ago, I wrote an article: Analysis of...

Several ways to encrypt and decrypt MySQL (summary)

Table of contents Written in front Two-way encryp...