VUE 调用PC摄像头,HTTP下也可以使用
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                VUE 调用PC摄像头,HTTP下也可以使用
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.                        
                                由于內(nèi)網(wǎng)使用,調(diào)用當(dāng)前pc的攝像頭,進(jìn)行拍照上傳功能,而瀏覽器由于安全策略考慮,只支持本地調(diào)用攝像頭,服務(wù)器上禁止使用,新版chrome支持修改安全協(xié)議,代碼如下:
chrome://flags/#unsafely-treat-insecure-origin-as-secure然后,將該 flag 切換成 enable 狀態(tài);
 在輸入框中填寫(xiě)需要開(kāi)啟的域名或地址例:http://xxx.xxx.xx.xx:1234,如果有多個(gè),則以逗號(hào)分隔;
 重啟瀏覽器后生效;
下面寫(xiě)了個(gè)子組件photo.vue,來(lái)調(diào)用,可以上傳多張照片,通過(guò)elemenui支持查看
<template><div><el-dialog v-el-drag-dialog width="720px" :title="title" :close-on-click-modal="false" :visible.sync="dialogPhotoVisible"><div v-show="!noShow" class="pictureBox"><div><div v-show="cameraShow" id="my_camera"><video id="videoCamera" :width="videoWidth" :height="videoHeight" autoplay></video><canvas style="display:none;" id="canvasCamera" :width="videoWidth" :height="videoHeight"></canvas></div><div v-show="!cameraShow" class="camera_no"><div><i class="el-icon-loading"/></div><div class="text">{{ loadingText }}</div></div></div><div class="picList"><div v-for="(s, index) in listSrc" style="position: relative"><el-imagestyle="width: 100%; height: 130px":src="s.src":preview-src-list="getSrcList(index)" lazy></el-image><i class="el-icon-error" @click="delClick(s)"></i></div></div></div><div v-show="noShow" class="camera_no_data"><div><i class="el-icon-loading"/></div><div class="text">{{ loadingErrorText }}</div></div><div class="btn-group" v-show="!noShow"><div class="btn-cn" v-show="cameraShow"><el-button type="warning" :loading="saveLoading" @click="takeSnapShot()">拍照</el-button><el-button v-if="listSrc.length !== 0" type="danger" :loading="saveLoading" @click="againTakePhoto()">清空</el-button><el-button type="primary" :loading="saveLoading" @click="saveSnapShot()">上傳</el-button></div></div><div slot="footer" class="dialog-footer"><el-button @click="dialogPhotoVisible = false">關(guān) 閉</el-button></div></el-dialog></div> </template> <script>import { dataToFile } from '@/utils/index'import { uploadApplyFiles } from '@/api/common'export default {name: 'PhotoApply',data() {return {dialogPhotoVisible: false,videoWidth: 480,videoHeight: 360,imgSrc: "",thisCancas: null,thisContext: null,thisVideo: null,stream: null,src: '',listSrc: [],takePhoto: true,cameraShow: false,saveLoading: false,noShow: false,loadingText: '正在加載攝像頭...',loadingErrorText: '正在加載攝像頭...'}},props: {title: {type: String}},watch: {dialogPhotoVisible(val) {if (val) {this.$nextTick(() => {this.open()})} else {this.listSrc = []this.close()}}},beforeDestroy() {this.listSrc = []},mounted() {},methods: {getSrcList(index){const srcs = this.listSrc.map((v) => { return v.src })return srcs.slice(index).concat(srcs.slice(0,index))},takeSnapShot() {const _this = thisconst timestamp = new Date().getTime()const fileName = _this.applyID + '_' + timestamp// canvas畫(huà)圖_this.thisContext.drawImage(_this.thisVideo,0,0,_this.videoWidth,_this.videoHeight);// 獲取圖片base64鏈接const image = _this.thisCancas.toDataURL("image/jpeg");_this.src = image_this.listSrc.push({src: _this.src,file: dataToFile(_this.src, fileName),title: fileName})_this.takePhoto = false},delClick(src) {this.listSrc = this.listSrc.filter((v) => {return src.src !== v.src})},againTakePhoto() {this.src = ''this.listSrc = []},saveSnapShot() {if (this.listSrc.length === 0) {this.$message.warning('請(qǐng)上傳相關(guān)數(shù)據(jù)')return}// 拍照const _this = this// 調(diào)用后臺(tái)接口_this.saveLoading = true_this.loadingText = '正在上傳圖片,請(qǐng)稍后...'let formData = new FormData()_this.listSrc.forEach((v) => {formData.append("images", v.file)})// 上傳自己可以自己寫(xiě)uploadApplyFiles(formData).then(res => {// const data = res.message_this.$message.success('上傳圖片成功')_this.dialogPhotoVisible = false}).catch(() => {setTimeout(() => {// 失敗_this.src = ''_this.saveLoading = false_this.takePhoto = true_this.cameraShow = true}, 500)})},close() {this.src = ''this.listSrc = []this.saveLoading = falsethis.cameraShow = falsethis.takePhoto = truethis.loadingText = '正在關(guān)閉攝像頭...'this.stopNavigator()},open() {this.cameraShow = falsethis.loadingText = '正在打開(kāi)攝像頭...'this.getCompetence()setTimeout(() => {this.cameraShow = true}, 1500)},// 調(diào)用權(quán)限(打開(kāi)攝像頭功能)getCompetence() {const _this = this;_this.thisCancas = document.getElementById("canvasCamera");_this.thisContext = this.thisCancas.getContext("2d");_this.thisVideo = document.getElementById("videoCamera");_this.thisVideo.style.display = 'block';// 獲取媒體屬性,舊版本瀏覽器可能不支持mediaDevices,我們首先設(shè)置一個(gè)空對(duì)象if (navigator.mediaDevices === undefined) {navigator.mediaDevices = {};}// 一些瀏覽器實(shí)現(xiàn)了部分mediaDevices,我們不能只分配一個(gè)對(duì)象// 使用getUserMedia,因?yàn)樗鼤?huì)覆蓋現(xiàn)有的屬性。// 這里,如果缺少getUserMedia屬性,就添加它。if (navigator.mediaDevices.getUserMedia === undefined) {navigator.mediaDevices.getUserMedia = function(constraints) {// 首先獲取現(xiàn)存的getUserMedia(如果存在)const getUserMedia =navigator.webkitGetUserMedia ||navigator.mozGetUserMedia ||navigator.getUserMedia;// 有些瀏覽器不支持,會(huì)返回錯(cuò)誤信息// 保持接口一致if (!getUserMedia) {//不存在則報(bào)錯(cuò)return Promise.reject(_this.$message.error("瀏覽器沒(méi)有打開(kāi)攝像頭的權(quán)限!"));}// 否則,使用Promise將調(diào)用包裝到舊的navigator.getUserMediareturn new Promise(function(resolve, reject) {getUserMedia.call(navigator, constraints, resolve, reject);});};}let constraints = {audio: false,video: {width: this.videoWidth,height: this.videoHeight,transform: "scaleX(-1)"}};navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {_this.stream = stream// 舊的瀏覽器可能沒(méi)有srcObjectif ("srcObject" in _this.thisVideo) {_this.thisVideo.srcObject = stream;} else {// 避免在新的瀏覽器中使用它,因?yàn)樗诒粭売谩this.thisVideo.src = window.URL.createObjectURL(stream);}_this.thisVideo.onloadedmetadata = function(e) {_this.thisVideo.play();};}).catch(err => {console.log(err);this.$nextTick(() => {this.noShow = truethis.loadingErrorText = '瀏覽器沒(méi)有打開(kāi)攝像頭的權(quán)限!在chrome瀏覽器的地址欄中輸入: chrome://flags/#unsafely-treat-insecure-origin-as-secure,將該 flag 切換成 enable 狀態(tài);\n' +'在輸入框中填寫(xiě)需要開(kāi)啟的域名或地址,如果有多個(gè),則以逗號(hào)分隔;\n' +'重啟瀏覽器后生效。'})});},// 關(guān)閉攝像頭stopNavigator() {if (this.stream) {if (this.stream.getVideoTracks) {let tracks = this.stream.getVideoTracks();if (tracks && tracks[0] && tracks[0].stop) tracks[0].stop();} else if (this.stream.stop) {this.stream.stop();}}}}} </script><style scoped lang="scss">.pictureBox {display: flex;align-items: center;justify-content: space-between;}.btn-cn {width: 100%;text-align: center;margin-top: 20px;margin-bottom: 20px;}#my_camera {border: 1px solid #606266;}.picList{width: 200px;overflow-x: hidden;overflow-y: scroll;height: 360px;.el-image{width: 180px;height: 130px;margin: 0px 0px 10px 10px;}}.camera_no_data{display: flex;flex-direction: column;justify-content: center;align-items: center;padding: 50px;width: 100%;margin-bottom: 20px;background: #fff;height: 360px;border: 1px solid #606266;.el-icon-loading {font-size: 40px;}.text {font-size: 20px;margin-top: 30px;}}.camera_no {position: relative;background: #fff;width: 480px;height: 360px;border: 1px solid #606266;display: flex;flex-direction: column;justify-content: center;align-items: center;.el-icon-loading {font-size: 40px;}.text {font-size: 20px;margin-top: 30px;}}::v-deep .el-image-viewer__mask {opacity: .9;background: #fff;}.el-icon-error{position: absolute;right: 0;top: 0;font-size: 25px;color: yellow;cursor: pointer;} </style>dataToFile.js
/*** 將base64轉(zhuǎn)換成file*/ export function dataToFile(base64, fileName){const parts = base64.split(';base64,')const contentType = parts[0].split(':')[1]const raw = window.atob(parts[1])const rawLength = raw.lengthconst uInt8Array = new Uint8Array(rawLength)for (let i = 0; i < rawLength; ++i) {uInt8Array[i] = raw.charCodeAt(i)}return new File([uInt8Array], fileName, {type: contentType, lastModified: Date.now()}) }父組件里調(diào)用
<photo red="photo" :title="'圖片拍照上傳'" />import photo from '......../photo.vue'components:{photo },methods: {openClick() {this.$refs['photo'].dialogPhotoVisible = true}}根據(jù)網(wǎng)上的博客來(lái)封裝了一下,由于關(guān)閉不了攝像頭,自己給改裝了一下
原文:
https://blog.csdn.net/RussW0/article/details/104694368/
總結(jié)
以上是生活随笔為你收集整理的VUE 调用PC摄像头,HTTP下也可以使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: iMacros 常用命令
- 下一篇: 如何成为一名合格的前端开发者?
