JavaScript实现调用摄像头完成拍照取图 重命名并下载或上传
环境条件
- 具有内置摄像头 或 外设摄像头
- 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>
- 静态效果
- 拍照后效果(上展示组件为Element的upload的
list-type="picture-card"
模式)
步骤解析
- 需要一个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});}},
- 准备数据
- 除了
fileListimg
和video
其他都不是必须的,根据自行需要准备
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",}},
- 初始化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}`);}
- 拍照
- 这一步是重点
上传
或下载
在这一步决定- 具体看注释
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)}
- 大功告成
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实现调用摄像头完成拍照取图 重命名并下载或上传相关推荐
- 调用android的拍照或本地相册选取再实现相片上传服务器,Android调用系统相机、本地相册上传图片(头像上传(裁剪)、多张图片上传)...
开发中基本上都会有头像上传的功能,有的app还需要多张图片同时上传,下面简单将头像上传以及多张图片上传功能整理一下.图片选择仿照微信选择图片的界面.[参考] 多图片选择器 !!!推荐一个动态权限请求的 ...
- 在网页中调用摄像头实现拍照上传 - 高拍仪二次开发
在网页中调用摄像头实现拍照上传 高拍仪二次开发 在一些公共部门的办事处,比如银行.护照办理中心.税务等,我们可能会注意到办公桌上摆着这样一台机器.办公人员用它拍摄各种证件.文件.表格,有时候还 ...
- c++ 二次开发 良田高拍仪_在网页中调用摄像头实现拍照上传 - 高拍仪二次开发...
来源于 https://blog.csdn.net/weixin_40659738/article/details/78252562 在网页中调用摄像头实现拍照上传 高拍仪二次开发 在一些公共部门的 ...
- 摄像头自建html直播,html5调用摄像头实现拍照
html5调用摄像头实现拍照 拍照 var video=document.getElementById("video"); var context=canvas.getContex ...
- vue实现PC端调用摄像头拍照人脸录入、移动端调用手机前置摄像头人脸录入、及图片旋转矫正、压缩上传base64格式/文件格式
PC端调用摄像头拍照上传base64格式到后台,这个没什么花里胡哨的骚操作,直接看代码 (canvas + video) <template><div><!--开启摄像头 ...
- Python+opencv调用摄像头实现拍照并保存
Python+opencv调用摄像头实现拍照并保存 安装 OpenCV库 详细源码 注意事项 安装 OpenCV库 pip install opencv-python 详细源码 调用外接摄像头实现拍照 ...
- android 实现自动拍照,android 调用摄像头自动拍照 并上传到YEELINK
前几天看到yeelink这个网站很感兴趣,注册了个图像传感器,就想着写个程序调用安卓摄像头并上传照片 程序很简单这个还是记录一下 首先是权限,分别是联网,相机,文件读取,照相和自动对焦的权限 然后是代 ...
- Python进阶,使用 opencv 调用摄像头进行拍照
opencv 支持 Python 版本的模块叫作 opencv-p hon ,可直接使用 pip install opencv-python 令进行安装,但常常会因为网络等问题导致失 ...
- C# winform窗体调用摄像头设备拍照
使用Aforge.dll第三方控件调用摄像头功能. 如图: 源码地址: https://pan.baidu.com/s/1jflhTnafZoFvOxh1c4hlsg 提取码: 8mut
最新文章
- LeetCode Weekly Contest 27
- object类中的equals与自定义equals方法详解
- 桐花万里python路-基础篇-05-字符串及浮点数
- Good Bye 2016 //智商再次下线,边界爆炸.....
- Sql Server CHAR类型
- win2003系统自动登录两法
- DynamipsGUI使用方法
- 计算机考研408真题
- 网易云自动签到云函数【详细版】-2022.5.4
- VMware虚拟机安装Kali破解WiFi密码
- 软银没有中国,孙正义失去一切
- RxJava2.0_1:基础学习和理解
- sugarnms如何快速实现网管软件定制开发?
- php gd表情包,gd表情包
- iOS Wow体验 - 第四章 - 为应用的上下文环境而设计
- STM32--学习笔记 常用协议总结
- 程序员生存定律--细论软件这个行当的根本特征
- 计算机管理无法格式化硬盘,为什么不能格式化硬盘?
- 学好电气全靠它,个人电气博文目录(持续更新中.....)
- SketchUp Pro2023安装包下载及安装教程
热门文章
- 手把手带你实现符合Promise/A+规范的Promise
- 视觉里程计 matlab实现,深度 | 视觉里程计---推导公式来了
- 矩阵分析与应用-6.2~6.3-奇异值分解-Section2
- 几种常见的建模工具比较(ROSE、PowerDesigner、VISIO、EA)
- 能链科技正式成为上海现代服务业联合会会员单位
- java使用siger 获取服务器硬件信息(CPU 内存 网络 io等)
- 服务微信生态及小程序创业,见实科技获微影资本500万天使投资
- 测试猿面试攻略?看这一篇足够了
- php版本下载,Windows版本PHP下载-PHP For Windows下载v7.4.13 官方最新版-西西软件下载...
- ChinaSkills-网络系统管理(2022年全国职业院校技能大赛 B模块真题)