废话不多说直接上代码
<template> <div> <el-button size="small" @click="handleOpen" >拍照 <i class="el-icon-camera el-icon--right"></i ></el-button> <el-dialog title="拍照" :visible.sync="cameraDialog" @close="closeclick" v-if="cameraDialog" :modal-append-to-body="false" :close-on-click-modal="false" width="600px" > <div class="camera-box" v-loading="loading"> <div class="camera-left"> <!-- 这里就是摄像头显示的画面 --> <video id="videoCamera" width="100%" height="100%"></video> </div> <div class="camera-right"> <div class="camera-img-box"> <div class="small-img"> <!-- 这里是点击拍照显示的图片画面 --> <img v-if="imgSrc" :src="imgSrc" style="width: 200px; height: 150px" /> <canvas id="canvasCamera" class="canvas" :width="videoWidth" :height="videoHeight" style="display: none" ></canvas> </div> <div> <!-- 点击拍照和保存按钮 --> <el-button type="primary" class="save-camera-btn" icon="el-icon-camera" @click="drawImage" style="margin-top: 10px" >拍照</el-button > <el-button type="primary" class="save-camera-btn" icon="el-icon-check" @click="uploadPicture" >保存</el-button > </div> </div> </div> </div> </el-dialog> </div> </template> <script> export default { components: {}, props: {}, data() { return { //相机 cameraDialog: false, os: false, //控制摄像头开关 imgSrc: undefined, thisVideo: null, thisContext: null, thisCancas: null, videoWidth: 500, videoHeight: 300, loading: true }; }, methods: { //拍照 handleOpen() { this.loading = true; this.cameraDialog = true; this.getCompetence(); }, getCompetence() { //必须在model中render后才可获取到dom节点,直接获取无法获取到model中的dom节点 this.$nextTick(() => { const _this = this; this.os = false; //切换成关闭摄像头 this.thisCancas = document.getElementById('canvasCamera'); //这里是需要截取的canvas的Id名称 this.thisContext = this.thisCancas.getContext('2d'); this.thisVideo = document.getElementById('videoCamera'); // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象 if (navigator.mediaDevices === undefined) { navigator.menavigatordiaDevices = {}; } // 一些浏览器实现了部分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)' } }; navigator.mediaDevices .getUserMedia(constraints) .then(function (stream) { // 旧的浏览器可能没有srcObject if ('srcObject' in _this.thisVideo) { _this.thisVideo.srcObject = stream; _this.loading = false; } 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链接,展示到界面中的也是这个url地址 this.imgSrc = this.thisCancas.toDataURL('image/png'); }, // 上传照相机图片 uploadPicture() { // 这里就调用上传图片接口即可 }, //清空画布 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.os = true; //切换成打开摄像头 } }, //关闭弹窗 closeclick() { this.cameraDialog = false; // 关闭照相机弹窗 this.resetCanvas(); // 重置画布 this.stopNavigator(); // 关闭摄像头 } } }; </script> <style lang="scss" scoped> </style>