生活随笔
收集整理的這篇文章主要介紹了
Vue 调用PC摄像头拍照
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
項目需求:可以本地上傳頭像,也可以選擇拍攝頭像上傳。
組件:
Camera組件:實現(xiàn) 打開、關(guān)閉攝像頭、繪制、顯示圖片、用于上傳CameraDialog組件:使用ElementUI dialog組件 展示攝像頭UI效果外部調(diào)用CameraDialog組件,實現(xiàn)拍攝頭像上傳功能本地上傳可使用原生input、也可使用ElementUI upload組件
操作邏輯:
新增時將頭像圖片轉(zhuǎn)為base64調(diào)用接口提交,返回url地址用于前端展示替換時,先執(zhí)行刪除操作,在依新增操作執(zhí)行。本地上傳原理跟拍攝上傳一致
具體實現(xiàn)方法:
<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
?'提示:請將頭像居中按"拍照"鍵確認(rèn)':''}}</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
: {show
: {type
: Boolean
},deleteData
: {type
: Object
}},data() {return {videoWidth
: '401',videoHeight
: '340',thisCancas
: null,thisContext
: null,thisVideo
: null,imgSrc
: ``,}},mounted() {if (this.show
) this.getCompetence()},methods
: {getCompetence() {var _this
= thisthis.thisCancas
= document
.getElementById('canvas')this.thisContext
= this.thisCancas
.getContext('2d')this.thisVideo
= document
.getElementById('video')if (navigator
.mediaDevices
=== undefined
) {navigator
.mediaDevices
= {}}if (navigator
.mediaDevices
.getUserMedia
=== undefined
) {navigator
.mediaDevices
.getUserMedia = function (constraints
) {var getUserMedia
= navigator
.webkitGetUserMedia
|| navigator
.mozGetUserMedia
|| navigator
.getUserMedia
if (!getUserMedia
) {return Promise
.reject(new Error('getUserMedia is not implemented in this browser'))}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
) {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_this
.thisContext
.drawImage(_this
.thisVideo
, 0, 0, _this
.videoWidth
, _this
.videoHeight
)var image
= this.thisCancas
.toDataURL('image/png')_this
.imgSrc
= image
},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
})},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
=> {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
>
<template
><div id
="camera-dialog"><el
-dialogtitle
="拍攝照片":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
)})},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(`確認(rèn)刪除?`, '提示', {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(() => {});},dialogCancleCamera(str
, filePath
, imagePath
) {this.dialogVisible
= str
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;}.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
>
以上只作為實現(xiàn)參考,具體操作依實際需求做相應(yīng)調(diào)整
總結(jié)
以上是生活随笔為你收集整理的Vue 调用PC摄像头拍照的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。