vue打开摄像头并上传图片到服务器

官方地址

<template>
	<div>
		<el-col :span="24" class="upload_img">
			<el-col :span="12">
				<el-col :span="4"><span>拍照上传</span></el-col>
				<el-button @click="onTake" icon="el-icon-camera" size="small">
					拍照上传
				</el-button>
			</el-col>
		</el-col>
		<el-col :span="24">
			<el-col :span="12">
				<el-col :offset="4">
					<el-image style="width: 100px; height: 100px" v-if="imgUrl" :src="'http://' + imgUrl" :fit="fit">
					</el-image>
				</el-col>
			</el-col>
		</el-col>
		<el-dialog title="拍照上传" :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-button v-if="open" @click="getCompetence" icon="el-icon-video-camera" size="small">
					打开摄像头
				</el-button>
				<el-button v-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>
	//拍照上传组件
	import {
		suppPic
	} from '@/axios/index'
	export default {
		name: "upload",
		data() {
			return {
				// imgUrl: '', //后端给返回的图片地址
				imgSrc: '', // base64的图片格式
				visible: false, //弹窗
				loading: false, //上传按钮加载
				open: false, //控制摄像头开关
				thisVideo: null,
				thisContext: null,
				thisCancas: null,
				videoWidth: 500,
				videoHeight: 400,
				front: true,
				fit: 'none',
				fileList: []
			}
		},
		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给file
					const 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('picture', conversions);
					this.loading = true;
					// axios接口
					suppPic(data).then(res => {
						if (res.data) this.$message({
							message: '保存成功',
							type: 'success'
						})
						this.loading = false
						this.imgUrl = 'http://' + res.data
						this.onCancel()
						this.$emit('imgObj', {
							upload: true,
							imgsrc: res.data
						})
					})

				} else {
					this.$message({
						message: '请点击拍照',
						error: '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.getUserMedia
							return 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)',
							facingMode: {
								exact: "environment"

							}
						}
					};
					navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
						// 旧的浏览器可能没有srcObject
						if ('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.$message({
							message: '没有开启摄像头权限',
							error: 'error'
						})
					});
				});
			},
			//绘制图片
			drawImage() {
				// 点击,canvas画图
				this.thisContext.drawImage(this.thisVideo, 0, 0, this.videoWidth, this.videoHeight);
				// 获取图片base64链接
				this.imgSrc = this.thisCancas.toDataURL('image/png');
			},
			dataURLtoFile(dataurl, filename) {
				var arr = dataurl.split(','),
					mime = arr[0].match(/:(.*?);/)[1],
					bstr = atob(arr[1]),
					n = bstr.length,
					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()
		},
		props: {
			imgUrl: String
		}
	}
</script>
// axios部分
export const suppPic = params => {
	const HOST = '' // 这里写你服务器的地址
	return axios.post(`${HOST}/api/Index/picture_upload`, params, {
		headers: {
			headers: {
				// 将from表单提交设置为富文本
				'Content-Type': 'multipart/form-data'
			}
		}
	})
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值