vue调用电脑摄像头,并利用canvas视频截图

<template>
    <div class="form-box">
        <el-form :model="form" :rules="rules" ref="ruleForm" label-width="100px" class="demo-studentForm">
            <el-form-item label="人脸信息" prop="faceBytes">
                <el-image :src="form.faceBytes" class="img-box mini-img">
                    <div slot="error" class="image-slot" style="text-align: center;font-size: 20px;">
                        请先拍照 -->
                    </div>
                </el-image>
                <el-button @click="handleOpen" size="small" style="position: relative;top:-10px;left: 10px;">{{form.faceBytes ? '重新拍照' : '点击拍照'}}</el-button>
            </el-form-item>
        </el-form>
        <el-row>
            <el-col :span="12" style="text-align: right;">
                <el-button @click="clearForm" type="warning" size="small">清 空</el-button>
                <el-button type="primary" @click="submitForm" size="small">确 定</el-button>
            </el-col>
        </el-row>

        <el-dialog title="摄像头拍照" :visible.sync="cameraOpen" :show-close="false" :close-on-press-escap="false" :close-on-click-modal="false">
            <el-row>
                <el-col :span="12">
                    <p class="title">摄&nbsp;&nbsp;&nbsp;&nbsp;像&nbsp;&nbsp;&nbsp;&nbsp;头</p>
                    <!-- 这里就是摄像头显示的画面 -->
                    <video id="videoCamera" class="video-box"></video>
                </el-col>
                <el-col :span="12">
                    <p class="title">照&nbsp;&nbsp;&nbsp;&nbsp;片</p>
                    <!-- 这里是点击拍照显示的图片画面 -->
                    <img v-show="form.faceBytes" :src="form.faceBytes" class="img-box" />
                    <canvas id="canvasCamera" class="canvas" :width='videoWidth' :height='videoHeight' style="display: none;"></canvas>
                </el-col>
            </el-row>
            <el-row>
                <el-col :span="12">
                    <el-button type="primary" icon="el-icon-camera" @click="drawImage">{{form.faceBytes ? '重新拍照' : '拍照'}}</el-button>
                </el-col>
                <el-col :span="12">
                    <el-button v-show="form.faceBytes" type="primary" icon="el-icon-check" @click="closeCameraMask">确定照片</el-button>
                </el-col>
            </el-row>
        </el-dialog>
    </div>
</template>

<script>
    import { mapState, mapMutations } from 'vuex'
    export default {
        data() {
            return {
                form: {
                    faceBytes: "",
                },
                rules: {
                    faceBytes: [{ required: true, message: '请录入人脸信息', trigger: 'blur' }],
                },
/** 照相机弹窗模块-start */
                cameraOpen: false,
                thisVideo: null,
                thisContext: null,
                thisCancas: null,
                videoWidth: 800,
                videoHeight: 600,
                /** 照相机弹窗模块-end */
            }
        },
        methods: {/** 调用摄像头拍照-start*/
            // 打开照相机弹窗
            handleOpen() {
                this.cameraOpen = true;
                this.getCompetence();
            },
            // 调用摄像头权限
            getCompetence() {
                //必须在model中render后才可获取到dom节点,直接获取无法获取到model中的dom节点
                this.$nextTick(() => {
                    const _this = this;
                    this.thisCancas = document.getElementById('canvasCamera'); //这里是需要截取的canvas的Id名称
                    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)' }
                    };
                    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 => {
                        console.log(err)
                        this.$notify({
                            title: '警告',
                            message: '没有开启摄像头权限或浏览器版本不兼容.',
                            type: 'warning'
                        });
                    });
                });
            },
            //绘制图片
            drawImage() {
                // 点击,canvas画图
                this.thisContext.drawImage(this.thisVideo, 0, 0, this.videoWidth, this.videoHeight);
                // 获取图片base64链接,展示到界面中的也是这个url地址
                this.form.faceBytes = this.thisCancas.toDataURL('image/png');
            },
            //重置画布
            resetCanvas() {
                this.form.faceBytes = "";
                this.thisContext.clearRect(0, 0, c.width, c.height);
            },
            // 关闭照相机弹窗
            closeCameraMask() {
                this.cameraOpen = false; // 关闭照相机弹窗
                // 关闭摄像头
                if (this.thisVideo && this.thisVideo !== null) {
                    this.thisVideo.srcObject.getTracks()[0].stop();
                }
            },
            /** 调用摄像头拍照-end*/

            submitForm() {
                this.$refs.ruleForm.validate((valid) => {
                    if (!valid) return false;
                    this.$api.addSignin(this.form).then(res => {
                        if (res) this.clearForm()
                    })
                });
            },
            //   清空数据
            clearForm(formName) {
                this.$refs.ruleForm.resetFields();
            }
        },
    };
</script>

 

posted @ 2023-03-10 10:59  HelpYourself!  阅读(196)  评论(0编辑  收藏  举报