VUE 调用PC摄像头,HTTP下也可以使用
由于内网使用,调用当前pc的摄像头,进行拍照上传功能,而浏览器由于安全策略考虑,只支持本地调用摄像头,服务器上禁止使用,新版chrome支持修改安全协议,代码如下:
chrome://flags/#unsafely-treat-insecure-origin-as-secure
然后,将该 flag 切换成 enable 状态;
在输入框中填写需要开启的域名或地址例:http://xxx.xxx.xx.xx:1234,如果有多个,则以逗号分隔;
重启浏览器后生效;
下面写了个子组件photo.vue,来调用,可以上传多张照片,通过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">关 闭</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画图_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('请上传相关数据')return}// 拍照const _this = this// 调用后台接口_this.saveLoading = true_this.loadingText = '正在上传图片,请稍后...'let formData = new FormData()_this.listSrc.forEach((v) => {formData.append("images", v.file)})// 上传自己可以自己写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 = '正在关闭摄像头...'this.stopNavigator()},open() {this.cameraShow = falsethis.loadingText = '正在打开摄像头...'this.getCompetence()setTimeout(() => {this.cameraShow = true}, 1500)},// 调用权限(打开摄像头功能)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,我们首先设置一个空对象if (navigator.mediaDevices === undefined) {navigator.mediaDevices = {};}// 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象// 使用getUserMedia,因为它会覆盖现有的属性。// 这里,如果缺少getUserMedia属性,就添加它。if (navigator.mediaDevices.getUserMedia === undefined) {navigator.mediaDevices.getUserMedia = function(constraints) {// 首先获取现存的getUserMedia(如果存在)const getUserMedia =navigator.webkitGetUserMedia ||navigator.mozGetUserMedia ||navigator.getUserMedia;// 有些浏览器不支持,会返回错误信息// 保持接口一致if (!getUserMedia) {//不存在则报错return Promise.reject(_this.$message.error("浏览器没有打开摄像头的权限!"));}// 否则,使用Promise将调用包装到旧的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// 旧的浏览器可能没有srcObjectif ("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);this.$nextTick(() => {this.noShow = truethis.loadingErrorText = '浏览器没有打开摄像头的权限!在chrome浏览器的地址栏中输入: chrome://flags/#unsafely-treat-insecure-origin-as-secure,将该 flag 切换成 enable 状态;\n' +'在输入框中填写需要开启的域名或地址,如果有多个,则以逗号分隔;\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转换成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()})
}
父组件里调用
<photo red="photo" :title="'图片拍照上传'" />import photo from '......../photo.vue'components:{photo
},methods: {openClick() {this.$refs['photo'].dialogPhotoVisible = true}}
根据网上的博客来封装了一下,由于关闭不了摄像头,自己给改装了一下
原文:
https://blog.csdn.net/RussW0/article/details/104694368/
VUE 调用PC摄像头,HTTP下也可以使用相关推荐
- Vue 调用PC摄像头拍照
项目需求:可以本地上传头像,也可以选择拍摄头像上传. 组件: Camera组件:实现 打开.关闭摄像头.绘制.显示图片.用于上传 CameraDialog组件:使用ElementUI dialog组件 ...
- VUE 调用PC摄像头 全浏览器可用
前几天项目有个需求 人脸识别 不想用flash这么恶心的组件 所有查找了网上一下资料 手撸了一个 可用浏览器 谷歌 火狐 360 UC QQ 当然都是基于三大内核的 (除了该死的IE都能 ...
- VUE 调用PC摄像头,亲测可用
首先声明一下,对于我的博客整理出来的.绝对是我自己亲测测试后有效果的,对于一些大佬说没用什么的,请仔细检查下您的代码!谢谢 在当前网页安全的情况下,浏览器会开启 navigator.mediaDevi ...
- vue 调用pc端本地摄像头、麦克风实现拍照、录视频、录音 并上传到服务器指定树文件夹
vue 调用pc端本地摄像头.麦克风实现拍照.录视频.录音 并上传 自己写blog只是为了下次方便使用 过程确实很烦 ,自己摸索加各大网站cv查看 可以直接使用 1.调用摄像头拍照 录屏 首先是npm ...
- vue调用本地摄像头实现拍照
前言: vue调用本地摄像头实现拍照功能,由于调用摄像头有使用权限,只能在本地运行,线上需用https域名才可以使用. 实现效果: 1.摄像头效果: 2.拍照效果: 实现代码: <templat ...
- js调用pc摄像头实现拍照、录视频等,新版Chrome无访问http页面无法打开麦克风、摄像头
js调用pc摄像头实现拍照.录视频等,新版Chrome无访问http页面无法打开麦克风.摄像头 新版Chrome配置 vue环境下的前端 function部分 ##由于没有https环境,只有http ...
- Vue调用本地摄像头权限
使用电脑本地摄像头的权限 关于如何调用本地摄像头的问题 准备工具 (VS Code,Vue脚手架工具,Element UI) vue调用本地摄像头实现拍照功能,由于调用摄像头有使用权限,只能在本地运行 ...
- html 调用pc摄像头,HTML调用PC摄像头
使用HTML5中的canvas和video技术实现调用PC摄像头 1.[代码][HTML]代码 HTML5调用电脑摄像头实例 window.addEventListener("DOMCont ...
- HTML调用PC摄像头【申明:来源于网络】
HTML调用PC摄像头[申明:来源于网络] ---- 地址:http://www.oschina.net/code/snippet_2440934_55195 <!DOCTYPE html> ...
最新文章
- javascript eval和JSON之间的联系
- OpenGL函数库详解
- Javascript与正则表达式
- 计算机二级证书如何考取,计算机二级证书怎么领 考试成绩怎么算
- 手把手教你安装Navicat——靠谱的Navicat安装教程
- minio扩展现有的分布式集群:扩大集群规模,增加磁盘数量
- 左神算法:最大值减去最小值小于或等于num的子数组的数量(Java版)
- 追洞小组 | Jdbc反序列化漏洞复现浅析
- MySQL占用系统进程_MySQL的Sleep进程占用大量连接解决方法
- 飞鸽传书:浅谈 Scrum
- spring5企业级开发实战 pdf_终于总结出Spring全家桶+微服务设计模式+Netty+MySQL调优PDF...
- 基于NFC的Android读写软件,NFC读写(android代码)
- 时间序列分析——自回归移动平均(ARMA)模型
- java 设置纸张大小设置_java page如何设置纸张
- 团队的英文翻译缩写_公司部门英文缩写简称大全
- ffmpeg命令下载m3u8原画质视频
- 2021-06-08实验室如何正确选择和确认检测方法?
- JavaScript------常用JS方法(utils.js)骨灰级总结
- STM32学习(窗口看门狗)
- 自动化软件测试流程的七个步骤和内容
热门文章
- 一个优秀的前端工程师简历应该是怎样的?
- DM8基于Linux安装(命令行)
- 抓取微信小程序源码教程,扒微信小程序文件等
- 机器学习笔试题练习(08-04)【4】
- 2022化工自动化控制仪表考试题库及答案
- opencv3+python3.5成语填字游戏(三)成语填字游戏解密算法
- 动态网页制作怎么这么难
- Wireshark—高级特性命令行模式
- 拓扑学 -- from BBS 水木清华站
- 显示器点距 测试软件,在小屏幕上使用高分的点距问题_液晶显示器_液晶显示器新闻-中关村在线...