环境条件

  • 具有内置摄像头 或 外设摄像头
  • Vue + Element + axios(环境不同可自行修改,本文主要为逻辑,除展示的上传控件其他与js基本无异)

全文

<template><div id="all"><el-upload:headers="{token:userinfo.token}"class="upload-demo"list-type="picture-card":multiple="false":limit="5":action="uploadimgUrl":on-success="uploadPhoto":on-remove="handleRemovePhoto":file-list="fileListimg"multiple><i class="el-icon-plus"></i></el-upload><div class="gp"><video ref="gpp2"></video></div><div class="footer" style="display: flex;justify-content: space-between;margin-top: 10px"><el-button type="primary" @click="takeGpp">抓 拍 上 传</el-button></div><canvas ref="canvas" v-show="false" height="960" width="1600"></canvas></div>
</template><script>
import request from "@/utils/request";export default {name: "demo",data(){let url = process.env.VUE_APP_BASE_API;let baseUrl = this.$baseUrl;let userinfo = JSON.parse(sessionStorage.getItem('userinfo'))return{fileListimg:[],fileliststr:"",video:{},baseUrl,userinfo,uploadimgUrl:url+"/upload_images",}},mounted() {this.initGpp();},methods:{openGpp() {// this.dialogFormVisible = true;setTimeout(() => {this.initGpp();}, 100)},initGpp() {this.video = this.$refs.gpp2;console.log(this.video)// this.video = document.getElementById('video')//兼容性写法,判断getUserMedia方法是否存在navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || window.getUserMedia;if (navigator.getUserMedia) {//调用用户媒体设备, 访问摄像头this.getUserMedia({video: {width: 1600, height: 960}}, this.success, this.error);} else {alert('不支持访问用户媒体');}},getUserMedia(constraints, success, error) {if (navigator.mediaDevices.getUserMedia) {//最新的标准APInavigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);} else if (navigator.webkitGetUserMedia) {//webkit核心浏览器navigator.webkitGetUserMedia(constraints, success, error)} else if (navigator.mozGetUserMedia) {//firfox浏览器navigator.mozGetUserMedia(constraints, success, error);} else if (navigator.getUserMedia) {//旧版APInavigator.getUserMedia(constraints, success, error);}},// 调用成功的方法success(stream) {//兼容webkit核心浏览器let CompatibleURL = window.URL || window.webkitURL;//将视频流设置为video元素的源// console.log(stream);//video.src = CompatibleURL.createObjectURL(stream);//将摄像头拍摄的视频赋值给viedeo的srcObject属性//src是视频文件,srcObject是实时流//摄像头是实时流this.video.srcObject = stream;//并播放this.video.play();},// 调用失败的方法error(error) {console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);},takeGpp() {if(this.fileListimg.length>=5){this.$message({type: 'error',message: "图片最多允许五张"});return}let canvas = this.$refs.canvas;var context = canvas.getContext("2d");//将视频当前的页面转换为图片,显示到画板中context.drawImage(this.video, 0, 0,);//把canvas图像转为img图片var src = canvas.toDataURL("image/jpeg");// console.log(src)let file = this.base64ToFile(src);let time = new Date().getTime();// this.downloadFile(file, `${time}.png`)let type = file.type.split('/');let renameFile = new File([file],time+".png",{type:"image/png"})let formData = new FormData();formData.append('file',renameFile)request({url:"/upload_images",method:"post",data:formData}).then(res => {console.log(res)this.$message({type: 'success',message: "上传成功"});this.fileListimg.push({status:"success",name:time+".png",uid:time,url:this.baseUrl + res.data.imgurl,response:res})})},base64ToFile(base64Data, fileName) {let arr = base64Data.split(','),fileType = arr[0].match(/:(.*?);/)[1],bstr = atob(arr[1]),l = bstr.length,u8Arr = new Uint8Array(l);while (l--) {u8Arr[l] = bstr.charCodeAt(l);}return new File([u8Arr], fileName, {type: fileType});},downloadFile(content, filename) {var a = document.createElement('a')var blob = new Blob([content])var url = window.URL.createObjectURL(blob)a.href = urla.download = filenamea.click()console.log(url)window.URL.revokeObjectURL(url)},handleRemovePhoto(file, fileList) {console.log(file, fileList);this.fileListimg = fileList;// let index=null;// fileList.map((item,i)=> {//   if(file.uid === item.uid){//     index = i;//   }// })// fileList.splice(index,1);},uploadPhoto(response, file, fileList) {file.url = this.baseUrl+response.data.imgurl;console.log(fileList)this.fileliststr = JSON.stringify(fileList)if(response.code == 0){// this.info.fujian = response.data.imgurl;// this.info.fujian_name = response.file_name;}else{// this.fileList = [];this.$message({type: 'error',message: response.msg});}},}
}
</script><style lang="scss" scoped>
#all {min-height: 100vh;background-color: #F5F7FD;padding: 10px 30px 60px;.gp {margin-top: 40px;height: 480px;width: 800px;video {height: 100%;width: 100%;}}}
</style>
  1. 静态效果
  2. 拍照后效果(上展示组件为Element的upload的list-type="picture-card"模式)

步骤解析

  1. 需要一个video控件和一个canvas控件(可隐藏)
  • canvas的大小将决定最终成像大小与质量
<div class="gp"><video ref="gpp2"></video>
</div>
<div class="footer" style="display: flex;justify-content: space-between;margin-top: 10px"><el-button type="primary" @click="takeGpp">抓 拍 上 传</el-button>
</div>
<canvas ref="canvas" v-show="false" height="960" width="1600"></canvas>
  • 这里我使用了一个来自Element的upload组件来展示,尽管你可能并不需要
 <el-upload:headers="{token:userinfo.token}"class="upload-demo"list-type="picture-card":multiple="false":limit="5":action="uploadimgUrl":on-success="uploadPhoto":on-remove="handleRemovePhoto":file-list="fileListimg"multiple><i class="el-icon-plus"></i></el-upload>handleRemovePhoto(file, fileList) {console.log(file, fileList);this.fileListimg = fileList;},uploadPhoto(response, file, fileList) {if(response.code == 0){file.url = this.baseUrl+response.data.imgurl;this.fileliststr = JSON.stringify(fileList)}else{this.$message({type: 'error',message: response.msg});}},
  1. 准备数据
  • 除了fileListimgvideo其他都不是必须的,根据自行需要准备
data(){let url = process.env.VUE_APP_BASE_API;let baseUrl = this.$baseUrl;let userinfo = JSON.parse(sessionStorage.getItem('userinfo'))return{fileListimg:[],fileliststr:"",video:{},baseUrl,userinfo,uploadimgUrl:url+"/upload_images",}},
  1. 初始化video和摄像头
  • 这一步网上的教程已经很多了
  • 在页面渲染完毕后调用initGpp()
initGpp() {this.video = this.$refs.gpp2;console.log(this.video)// this.video = document.getElementById('video')//兼容性写法,判断getUserMedia方法是否存在navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || window.getUserMedia;if (navigator.getUserMedia) {//调用用户媒体设备, 访问摄像头this.getUserMedia({video: {width: 1600, height: 960}}, this.success, this.error);} else {alert('不支持访问用户媒体');}},getUserMedia(constraints, success, error) {if (navigator.mediaDevices.getUserMedia) {//最新的标准APInavigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);} else if (navigator.webkitGetUserMedia) {//webkit核心浏览器navigator.webkitGetUserMedia(constraints, success, error)} else if (navigator.mozGetUserMedia) {//firfox浏览器navigator.mozGetUserMedia(constraints, success, error);} else if (navigator.getUserMedia) {//旧版APInavigator.getUserMedia(constraints, success, error);}},// 调用成功的方法success(stream) {//兼容webkit核心浏览器let CompatibleURL = window.URL || window.webkitURL;//将视频流设置为video元素的源// console.log(stream);//video.src = CompatibleURL.createObjectURL(stream);//将摄像头拍摄的视频赋值给viedeo的srcObject属性//src是视频文件,srcObject是实时流//摄像头是实时流this.video.srcObject = stream;//并播放this.video.play();},// 调用失败的方法error(error) {console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);}
  1. 拍照
  • 这一步是重点
  • 上传下载在这一步决定
  • 具体看注释
 takeGpp() {// 在这里可以做一些前期校验 if(this.fileListimg.length>=5){this.$message({type: 'error',message: "图片最多允许五张"});return}let canvas = this.$refs.canvas;var context = canvas.getContext("2d");//将视频当前的页面转换为图片,显示到画板中context.drawImage(this.video, 0, 0,);//把canvas图像转为img图片var src = canvas.toDataURL("image/jpeg");let file = this.base64ToFile(src);// 获取时间,准备当做文件名let time = new Date().getTime();// 如果你需要是下载,那么请将下一行解除注释,并将下一行以下的内容全部删除// this.downloadFile(file, `${time}.png`)// 重命名文件并改变格式 let type = file.type.split('/');let renameFile = new File([file],time+".png",{type:"image/png"})let formData = new FormData();formData.append('file',renameFile)// 上传 request封装方法 继续阅读request({url:"/upload_images",method:"post",data:formData}).then(res => {console.log(res)this.$message({type: 'success',message: "上传成功"});// 这里是为了使用Element的upload组件展示而做的,向该数组添加相似结构数据// 请根据自行需要this.fileListimg.push({status:"success",name:time+".png",uid:time,url:this.baseUrl + res.data.imgurl,response:res})})},base64ToFile(base64Data, fileName) {let arr = base64Data.split(','),fileType = arr[0].match(/:(.*?);/)[1],bstr = atob(arr[1]),l = bstr.length,u8Arr = new Uint8Array(l);while (l--) {u8Arr[l] = bstr.charCodeAt(l);}return new File([u8Arr], fileName, {type: fileType});},// 下载会用到该方法downloadFile(content, filename) {var a = document.createElement('a')var blob = new Blob([content])var url = window.URL.createObjectURL(blob)a.href = urla.download = filenamea.click()console.log(url)window.URL.revokeObjectURL(url)}
  1. 大功告成

request.js

  • 参考了Vue-admin-template的封装设计
import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
import store from '@/store'const service = axios.create({baseURL: process.env.VUE_APP_BASE_API, // url = base url + request urltimeout: 10000 // request timeout
})service.interceptors.request.use(config => {let token = sessionStorage.getItem("token")if(token){config.headers['token'] = token;}return config},error => {console.log(error) return Promise.reject(error)}
)service.interceptors.response.use(response => {const res = response.dataif (res.code === 3) {// 未登录Message.error("未登录")store.dispatch('user/logout').then(() => {location.reload()})return Promise.reject(new Error(res.message || 'Error'))}return res},error => {console.log('err' + error) // for debugMessage({message: error.message,type: 'error',duration: 5 * 1000})return Promise.reject(error)}
)export default service

JavaScript实现调用摄像头完成拍照取图 重命名并下载或上传相关推荐

  1. 调用android的拍照或本地相册选取再实现相片上传服务器,Android调用系统相机、本地相册上传图片(头像上传(裁剪)、多张图片上传)...

    开发中基本上都会有头像上传的功能,有的app还需要多张图片同时上传,下面简单将头像上传以及多张图片上传功能整理一下.图片选择仿照微信选择图片的界面.[参考] 多图片选择器 !!!推荐一个动态权限请求的 ...

  2. 在网页中调用摄像头实现拍照上传 - 高拍仪二次开发

    在网页中调用摄像头实现拍照上传 高拍仪二次开发     在一些公共部门的办事处,比如银行.护照办理中心.税务等,我们可能会注意到办公桌上摆着这样一台机器.办公人员用它拍摄各种证件.文件.表格,有时候还 ...

  3. c++ 二次开发 良田高拍仪_在网页中调用摄像头实现拍照上传 - 高拍仪二次开发...

    来源于  https://blog.csdn.net/weixin_40659738/article/details/78252562 在网页中调用摄像头实现拍照上传 高拍仪二次开发 在一些公共部门的 ...

  4. 摄像头自建html直播,html5调用摄像头实现拍照

    html5调用摄像头实现拍照 拍照 var video=document.getElementById("video"); var context=canvas.getContex ...

  5. vue实现PC端调用摄像头拍照人脸录入、移动端调用手机前置摄像头人脸录入、及图片旋转矫正、压缩上传base64格式/文件格式

    PC端调用摄像头拍照上传base64格式到后台,这个没什么花里胡哨的骚操作,直接看代码 (canvas + video) <template><div><!--开启摄像头 ...

  6. Python+opencv调用摄像头实现拍照并保存

    Python+opencv调用摄像头实现拍照并保存 安装 OpenCV库 详细源码 注意事项 安装 OpenCV库 pip install opencv-python 详细源码 调用外接摄像头实现拍照 ...

  7. android 实现自动拍照,android 调用摄像头自动拍照 并上传到YEELINK

    前几天看到yeelink这个网站很感兴趣,注册了个图像传感器,就想着写个程序调用安卓摄像头并上传照片 程序很简单这个还是记录一下 首先是权限,分别是联网,相机,文件读取,照相和自动对焦的权限 然后是代 ...

  8. Python进阶,使用 opencv 调用摄像头进行拍照

             opencv 支持 Python 版本的模块叫作 opencv-p hon ,可直接使用 pip install opencv-python 令进行安装,但常常会因为网络等问题导致失 ...

  9. C# winform窗体调用摄像头设备拍照

    使用Aforge.dll第三方控件调用摄像头功能. 如图: 源码地址: https://pan.baidu.com/s/1jflhTnafZoFvOxh1c4hlsg 提取码: 8mut

最新文章

  1. LeetCode Weekly Contest 27
  2. object类中的equals与自定义equals方法详解
  3. 桐花万里python路-基础篇-05-字符串及浮点数
  4. Good Bye 2016 //智商再次下线,边界爆炸.....
  5. Sql Server CHAR类型
  6. win2003系统自动登录两法
  7. DynamipsGUI使用方法
  8. 计算机考研408真题
  9. 网易云自动签到云函数【详细版】-2022.5.4
  10. VMware虚拟机安装Kali破解WiFi密码
  11. 软银没有中国,孙正义失去一切
  12. RxJava2.0_1:基础学习和理解
  13. sugarnms如何快速实现网管软件定制开发?
  14. php gd表情包,gd表情包
  15. iOS Wow体验 - 第四章 - 为应用的上下文环境而设计
  16. STM32--学习笔记 常用协议总结
  17. 程序员生存定律--细论软件这个行当的根本特征
  18. 计算机管理无法格式化硬盘,为什么不能格式化硬盘?
  19. 学好电气全靠它,个人电气博文目录(持续更新中.....)
  20. SketchUp Pro2023安装包下载及安装教程

热门文章

  1. 手把手带你实现符合Promise/A+规范的Promise
  2. 视觉里程计 matlab实现,深度 | 视觉里程计---推导公式来了
  3. 矩阵分析与应用-6.2~6.3-奇异值分解-Section2
  4. 几种常见的建模工具比较(ROSE、PowerDesigner、VISIO、EA)
  5. 能链科技正式成为上海现代服务业联合会会员单位
  6. java使用siger 获取服务器硬件信息(CPU 内存 网络 io等)
  7. 服务微信生态及小程序创业,见实科技获微影资本500万天使投资
  8. 测试猿面试攻略?看这一篇足够了
  9. php版本下载,Windows版本PHP下载-PHP For Windows下载v7.4.13 官方最新版-西西软件下载...
  10. ChinaSkills-网络系统管理(2022年全国职业院校技能大赛 B模块真题)