Vue calls PC camera to realize photo taking function
- 2021-11-23 22:08:31
- OfStack
In this paper, we share the specific code of Vue calling PC camera to realize the photo function for your reference. The specific contents are as follows
Project requirements: You can upload your avatar locally, or you can choose to shoot your avatar and upload it.
Components:
1. Camera component: Open and close the camera, draw and display pictures for uploading
2. CameraDialog component: Use ElementUI dialog component to show the UI effect of camera
3. Call CameraDialog component externally to realize the uploading function of shooting avatar
4. Native input or ElementUI upload components can be used for local uploading
Operational logic:
1. When adding, convert the avatar picture to base64 calling interface for submission, and return url address for front-end display
2. When replacing, the deletion operation is performed first, and then the new operation is performed.
3. Local upload principle and shooting upload 1
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 " Photographing " Key confirmation ':''}}</p>
<el-button type="primary" @click="setImage" v-if="!imgSrc" class="camera-btn"> Photographing </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: {
// "Must choose" CameraDialog Pop-up display status
show: {type: Boolean},
// "Optional" with native input Upload locally to perform deletion 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 Invoke 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 it at all mediaDevices We first set the 1 Empty object
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {}
}
// 1 Some browsers have implemented some mediaDevices We can't just distribute 1 Objects
// Use getUserMedia Because it overrides existing properties.
// Here, if there is a lack of getUserMedia Property, 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
// Maintain interface 1 To
if (!getUserMedia) {
return Promise.reject(new Error('getUserMedia is not implemented in this browser'))
}
// Otherwise, use the Promise Wrap the call to the old 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) {
// Old browsers may not have srcObject
if ('srcObject' in _this.thisVideo) {
_this.thisVideo.srcObject = stream
} else {
// Avoid using it in new browsers because 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 a picture
*****************************************/
setImage() {
var _this = this
// Click, canvas Draw a picture
_this.thisContext.drawImage(_this.thisVideo, 0, 0, _this.videoWidth, _this.videoHeight)
// Get a picture base64 Link
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 File transfer
*****************************************/
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 Turn off the camera
*****************************************/
stopNavigator() {
this.thisVideo.srcObject.getTracks()[0].stop()
},
// Upload pictures
setFileUpload() {
// Edit a file - Upload face photos
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 succeeded ", 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 succeeded ", type: "success"})
})
.catch(err => {
console.log(err)
})
})
.catch(err => {
console.log(err)
})
}
} else {
// Adding Household - Upload face photos
setFileUpload({image: this.imgSrc})
.then(res => {
// console.log(res)
this.$message({message: " Upload succeeded ", 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 photograph "
: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"> Take Elimination </el-button> -->
<!-- <el-button type="primary"> Indeed Fixed </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 Face Photo Address
fileUpload(filePath, imagePath) {
this.filePath = filePath
this.imagePath = imagePath
this.dialogCancle()
}
}
}
</script>
<style scoped>
</style>
External calling 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 photograph </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 Avatar
dialogVisible: false,
// Action to delete the related fields of face photos
deleteData: {
userid: this.$route.query.userId,
id: ``,
cardType: 4,
imagePath: ``,
}
}
},
methods: {
// Simulate clicking to upload face photos locally
localUploadFile() {
this.$refs.inputFile.click()
},
// Upload face photos locally
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 photos
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 is not shown
this.getInfo()
})
.catch(err => {
console.log(err)
})
})
.catch(err => {
console.log(err)
})
},
// Turn 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 photos
deleteUploadFile() {
this.$confirm(` Confirm deletion ?`, ' Prompt ', {
confirmButtonText: ' Determine ',
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(() => {});
},
//Dialog Cancel the 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, and the specific operation is adjusted according to the actual needs.