由于内网使用,调用当前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下也可以使用相关推荐

  1. Vue 调用PC摄像头拍照

    项目需求:可以本地上传头像,也可以选择拍摄头像上传. 组件: Camera组件:实现 打开.关闭摄像头.绘制.显示图片.用于上传 CameraDialog组件:使用ElementUI dialog组件 ...

  2. VUE 调用PC摄像头 全浏览器可用

    前几天项目有个需求  人脸识别   不想用flash这么恶心的组件  所有查找了网上一下资料 手撸了一个 可用浏览器  谷歌 火狐 360 UC  QQ  当然都是基于三大内核的 (除了该死的IE都能 ...

  3. VUE 调用PC摄像头,亲测可用

    首先声明一下,对于我的博客整理出来的.绝对是我自己亲测测试后有效果的,对于一些大佬说没用什么的,请仔细检查下您的代码!谢谢 在当前网页安全的情况下,浏览器会开启 navigator.mediaDevi ...

  4. vue 调用pc端本地摄像头、麦克风实现拍照、录视频、录音 并上传到服务器指定树文件夹

    vue 调用pc端本地摄像头.麦克风实现拍照.录视频.录音 并上传 自己写blog只是为了下次方便使用 过程确实很烦 ,自己摸索加各大网站cv查看 可以直接使用 1.调用摄像头拍照 录屏 首先是npm ...

  5. vue调用本地摄像头实现拍照

    前言: vue调用本地摄像头实现拍照功能,由于调用摄像头有使用权限,只能在本地运行,线上需用https域名才可以使用. 实现效果: 1.摄像头效果: 2.拍照效果: 实现代码: <templat ...

  6. js调用pc摄像头实现拍照、录视频等,新版Chrome无访问http页面无法打开麦克风、摄像头

    js调用pc摄像头实现拍照.录视频等,新版Chrome无访问http页面无法打开麦克风.摄像头 新版Chrome配置 vue环境下的前端 function部分 ##由于没有https环境,只有http ...

  7. Vue调用本地摄像头权限

    使用电脑本地摄像头的权限 关于如何调用本地摄像头的问题 准备工具 (VS Code,Vue脚手架工具,Element UI) vue调用本地摄像头实现拍照功能,由于调用摄像头有使用权限,只能在本地运行 ...

  8. html 调用pc摄像头,HTML调用PC摄像头

    使用HTML5中的canvas和video技术实现调用PC摄像头 1.[代码][HTML]代码 HTML5调用电脑摄像头实例 window.addEventListener("DOMCont ...

  9. HTML调用PC摄像头【申明:来源于网络】

    HTML调用PC摄像头[申明:来源于网络] ---- 地址:http://www.oschina.net/code/snippet_2440934_55195 <!DOCTYPE html> ...

最新文章

  1. javascript eval和JSON之间的联系
  2. OpenGL函数库详解
  3. Javascript与正则表达式
  4. 计算机二级证书如何考取,计算机二级证书怎么领 考试成绩怎么算
  5. 手把手教你安装Navicat——靠谱的Navicat安装教程
  6. minio扩展现有的分布式集群:扩大集群规模,增加磁盘数量
  7. 左神算法:最大值减去最小值小于或等于num的子数组的数量(Java版)
  8. 追洞小组 | Jdbc反序列化漏洞复现浅析
  9. MySQL占用系统进程_MySQL的Sleep进程占用大量连接解决方法
  10. 飞鸽传书:浅谈 Scrum
  11. spring5企业级开发实战 pdf_终于总结出Spring全家桶+微服务设计模式+Netty+MySQL调优PDF...
  12. 基于NFC的Android读写软件,NFC读写(android代码)
  13. 时间序列分析——自回归移动平均(ARMA)模型
  14. java 设置纸张大小设置_java page如何设置纸张
  15. 团队的英文翻译缩写_公司部门英文缩写简称大全
  16. ffmpeg命令下载m3u8原画质视频
  17. 2021-06-08实验室如何正确选择和确认检测方法?
  18. JavaScript------常用JS方法(utils.js)骨灰级总结
  19. STM32学习(窗口看门狗)
  20. 自动化软件测试流程的七个步骤和内容

热门文章

  1. 一个优秀的前端工程师简历应该是怎样的?
  2. DM8基于Linux安装(命令行)
  3. 抓取微信小程序源码教程,扒微信小程序文件等
  4. 机器学习笔试题练习(08-04)【4】
  5. 2022化工自动化控制仪表考试题库及答案
  6. opencv3+python3.5成语填字游戏(三)成语填字游戏解密算法
  7. 动态网页制作怎么这么难
  8. Wireshark—高级特性命令行模式
  9. 拓扑学 -- from BBS 水木清华站
  10. 显示器点距 测试软件,在小屏幕上使用高分的点距问题_液晶显示器_液晶显示器新闻-中关村在线...