700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > vue+elementUI实现调用PC摄像头拍照上传图片(谷歌火狐测试可用 其他自测)

vue+elementUI实现调用PC摄像头拍照上传图片(谷歌火狐测试可用 其他自测)

时间:2020-03-15 12:11:58

相关推荐

vue+elementUI实现调用PC摄像头拍照上传图片(谷歌火狐测试可用 其他自测)

一定部署到https域名上,否则无法调用摄像头权限!!!

效果图

定义Data

data () {return {dialogTableVisible:false,videoWidth: 500,videoHeight: 400,imgSrc: '',thisCancas: null,thisContext: null,thisVideo: null,ImgFile:'',//返回的图片文件}},

调用摄像头权限

getCompetence () {this.$nextTick(function () {var _this = this;this.thisCancas = document.getElementById('canvasCamera');this.thisContext = this.thisCancas.getContext('2d');this.thisVideo = document.getElementById('videoCamera');// 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象if (navigator.mediaDevices === undefined) {navigator.mediaDevices = {}}// 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象// 使用getUserMedia,因为它会覆盖现有的属性。// 这里,如果缺少getUserMedia属性,就添加它。if (navigator.mediaDevices.getUserMedia === undefined) {navigator.mediaDevices.getUserMedia = function (constraints) {// 首先获取现存的getUserMedia(如果存在)var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia;// 有些浏览器不支持,会返回错误信息// 保持接口一致if (!getUserMedia) {return Promise.reject(new Error('getUserMedia is not implemented in this browser'))}// 否则,使用Promise将调用包装到旧的navigator.getUserMediareturn new Promise(function (resolve, reject) {getUserMedia.call(navigator, constraints, resolve, reject)})}}var constraints = { audio: false, video: { width: this.videoWidth, height: this.videoHeight, transform: 'scaleX(-1)' } };navigator.mediaDevices.getUserMedia(constraints).then(function (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)})});},

绘制图片,生成一个base64文件

setImage(){var _this = this;// 点击,canvas画图_this.thisContext.drawImage(_this.thisVideo, 0, 0, _this.videoWidth, _this.videoHeight);// 获取图片base64链接var image = this.thisCancas.toDataURL('image/png');_this.imgSrc = image;},

base64文件转文件流

dataURLtoFile (dataurl, filename) {var arr = dataurl.split(',');var mime = arr[0].match(/:(.*?);/)[1];var bstr = atob(arr[1]);var n = bstr.length;var u8arr = new Uint8Array(n);while (n--) {u8arr[n] = bstr.charCodeAt(n)}return new File([u8arr], filename, { type: mime })},

上传文件流至后台(form提交)

handleUpdata(){//已form提交if (this.imgSrc!==''){let file = this.imgSrc; // 把整个base64给filelet type = "image/jpeg"; // 定义图片类型(canvas转的图片一般都是png,也可以指定其他类型)let time=(new Date()).valueOf();//生成时间戳let name = time + ".jpg"; // 定义文件名字(例如:abc.png , cover.png)let conversions = this.dataURLtoFile(file, name); // 调用base64转图片方法let parms=new FormData();parms.append('file',conversions);let url='*********';//你的接口this.axios.post(url,parms,{headers: {'Content-Type': 'multipart/form-data'}}).then(res=>{console.log(res);this.ImgFile=res.data;}).catch(err=>{this.$notify.error({title: '上传失败',message: err.msg});})}},

关闭摄像头

stopNavigator () {this.thisVideo.srcObject.getTracks()[0].stop()},

离开页面时关闭摄像头

beforeDestroy () {this.stopNavigator()}

附上源码:

<template><div><el-button@click="onTake"icon="el-icon-camera"size="small">拍照上传</el-button><el-dialogtitle="拍照上传":visible.sync="visible"@close="onCancel"width="1065px"><div class="box"><video id="videoCamera" class="canvas" :width="videoWidth" :height="videoHeight" autoPlay></video><canvas id="canvasCamera" class="canvas" :width="videoWidth" :height="videoHeight"></canvas></div><div slot="footer"><el-button@click="drawImage"icon="el-icon-camera"size="small">拍照</el-button><el-buttonv-if="open"@click="getCompetence"icon="el-icon-video-camera"size="small">打开摄像头</el-button><el-buttonv-else@click="stopNavigator"icon="el-icon-switch-button"size="small">关闭摄像头</el-button><el-button@click="resetCanvas"icon="el-icon-refresh"size="small">重置</el-button><el-button@click="onCancel"icon="el-icon-circle-close"size="small">取消</el-button><el-button@click="onUpload":loading="loading"type="primary"icon="el-icon-upload2"size="small">上传</el-button></div></el-dialog></div></template><script>//拍照上传组件//父组件通过函数 getImg 获取照片路径,如 @getImg="getImg"const Address = require('../utils/url');//图片上传地址export default {name: "TakePhotos",data() {return {imgSrc: "",visible: false,//弹窗loading: false,//上传按钮加载open: false,//控制摄像头开关thisVideo: null,thisContext: null,thisCancas: null,videoWidth: 500,videoHeight: 400}},methods: {onTake() {this.visible = true;this.getCompetence();},onCancel() {this.visible = false;this.resetCanvas();this.stopNavigator();},//base64转成文件后上传onUpload() {if (this.imgSrc) {const file = this.imgSrc; // 把整个base64给fileconst time = (new Date()).valueOf();//生成时间戳const name = time + ".png"; // 定义文件名字(例如:abc.png , cover.png)const conversions = this.dataURLtoFile(file, name); // 调用base64转图片方法const data = new FormData();data.append('file', conversions);const options = {method: "POST", //请求方法body: data, //请求体headers: {'Accept': 'application/json'},};this.loading = true;fetch(Address.UPLOAD, options).then((response) => {return response.json();}).then((responseText) => {this.loading = false;if (responseText.code === 0) {this.imgSrc = responseText.data.src;this.$emit('getImg', responseText.data.src);//传递给父组件this.onCancel();this.$notify({title: '上传成功',message: responseText.msg,type: 'success'});}}).catch((error) => {this.loading = false;this.$notify.error({title: '上传失败',message: error.msg,});})}else {this.$notify({title: '警告',message: '请点击拍照',type: 'warning'});}},// 调用摄像头权限getCompetence() {//必须在model中render后才可获取到dom节点,直接获取无法获取到model中的dom节点this.$nextTick(() => {const _this = this;this.open = false;//切换成关闭摄像头this.thisCancas = document.getElementById('canvasCamera');this.thisContext = this.thisCancas.getContext('2d');this.thisVideo = document.getElementById('videoCamera');// 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象if (navigator.mediaDevices === undefined) {navigator.mediaDevices = {}}// 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象// 使用getUserMedia,因为它会覆盖现有的属性。// 这里,如果缺少getUserMedia属性,就添加它。if (navigator.mediaDevices.getUserMedia === undefined) {navigator.mediaDevices.getUserMedia = function (constraints) {// 首先获取现存的getUserMedia(如果存在)let getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia;// 有些浏览器不支持,会返回错误信息// 保持接口一致if (!getUserMedia) {return Promise.reject(new Error('getUserMedia is not implemented in this browser'))}// 否则,使用Promise将调用包装到旧的navigator.getUserMediareturn new Promise(function (resolve, reject) {getUserMedia.call(navigator, constraints, resolve, reject)})}}const constraints = {audio: false,video: {width: _this.videoWidth, height: _this.videoHeight, transform: 'scaleX(-1)'}};navigator.mediaDevices.getUserMedia(constraints).then(function (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 => {this.$notify({title: '警告',message: '没有开启摄像头权限或浏览器版本不兼容.',type: 'warning'});});});},//绘制图片drawImage() {// 点击,canvas画图this.thisContext.drawImage(this.thisVideo, 0, 0, this.videoWidth, this.videoHeight);// 获取图片base64链接this.imgSrc = this.thisCancas.toDataURL('image/png');},//base64转文件dataURLtoFile(dataurl, filename) {let arr = dataurl.split(',');let mime = arr[0].match(/:(.*?);/)[1];let bstr = atob(arr[1]);let n = bstr.length;let u8arr = new Uint8Array(n);while (n--) {u8arr[n] = bstr.charCodeAt(n)}return new File([u8arr], filename, {type: mime})},//清空画布clearCanvas(id) {let c = document.getElementById(id);let cxt = c.getContext("2d");cxt.clearRect(0, 0, c.width, c.height);},//重置画布resetCanvas() {this.imgSrc = "";this.clearCanvas('canvasCamera');},//关闭摄像头stopNavigator() {if (this.thisVideo && this.thisVideo !== null) {this.thisVideo.srcObject.getTracks()[0].stop();this.open = true;//切换成打开摄像头}},},beforeDestroy() {this.stopNavigator()}}</script><style scoped>.box {display: flex;justify-content: space-between;}.canvas {border: 1px solid #e8e8e8;}</style>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。