vue浏览器调用摄像头实现拍照上传

1、自定义调用摄像头组件-放在一个对话框中显示

<el-dialog
    title="人脸识别"
    :visible.sync="dialogVisible"
    top="5vh"
    width="481px"
    :close-on-click-modal="false"
    :show-close="false"
    :close-on-press-escape="false">
        <Camera :show="dialogVisible" :loading="loading" @setFileUpload="setFileUpload"></Camera>
</el-dialog>

2、camera组件内容:(实现调起摄像头拍照上传功能)

<template>
    <div class="camera-box">
        <video id="video" :width="videoWidth" :height="videoHeight" v-show="!imgSrc"></video>
        <canvas id="canvas" :width="videoWidth" :height="videoHeight" v-show="imgSrc"></canvas>
        <p class="camera-p">{{ !imgSrc ? '提示:请将人脸居中按"拍照"键确认' : '' }}</p>

        <el-button type="primary" @click="imgSrc = ''" v-if="imgSrc" class="camera-btn">返回重新拍照</el-button>
        <el-button type="primary" @click="setImage" v-if="!imgSrc" class="camera-btn">拍照</el-button>
        <el-button type="primary" :loading="loading" v-if="imgSrc" @click="setFileUpload" class="camera-btn">上传</el-button>
    </div>
</template>

<script>
export default {
    name: 'Camera',
    props: {
        //【必选】CameraDialog弹窗显示状态
        show: { type: Boolean },
        loading: { type: Boolean },
        //【可选】配合原生input本地上传,用于替换时执行删除
        // deleteData: { type: Object },
    },
    data() {
        return {
            videoWidth: '401',
            videoHeight: '340',
            thisCancas: null,
            thisContext: null,
            thisVideo: null,
            imgSrc: ``,
        }
    },
    mounted() {
        if (this.show) this.getCompetence()
    },
    methods: {
        /*
         *@author Brady
         *@Time 2019/9/5
         *@function  调用权限
         *****************************************/
        getCompetence() {
            var _this = this
            this.thisCancas = document.getElementById('canvas')
            this.thisContext = this.thisCancas.getContext('2d')
            this.thisVideo = document.getElementById('video')
            // 旧版本浏览器可能根本不支持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.getUserMedia
                    return 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) {
                // 旧的浏览器可能没有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)
            })
        },
        /*
         *@author Brady
         *@Time 2019/9/5
         *@function  绘制图片
         *****************************************/
        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
            // console.log(_this.imgSrc)
            // this.$emit('refreshDataList', this.imgSrc)
        },
        /*
         *@author Brady
         *@Time 2019/9/5
         *@function  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 })
        },
        /*
         *@author Brady
         *@Time 2019/9/5
         *@function  关闭摄像头
         *****************************************/
        stopNavigator() {
            // this.thisVideo.srcObject.getTracks()[0].stop()
        },
        //上传图片
        setFileUpload() {
            // console.log(this.imgSrc,'=====')
            this.$emit('setFileUpload',this.imgSrc)
        },
    },
    watch: {
        show(val) {
            if (val) {
                this.imgSrc = ``
                this.getCompetence()
            } else {
                this.stopNavigator()
            }
        },
    }
}
</script>

<style lang="less" scoped>
.camera-box {
    margin: 0 auto;
    text-align: center;

    .camera-p {
        height: 17px;
        line-height: 17px;
        font-size: 12px;
        font-family: "PingFang SC";
        font-weight: 400;
        color: rgba(154, 154, 154, 1);
        text-align: left;
    }

    .camera-btn {
        margin-top: 20px;
    }

}
</style>

开发遇到的问题:

①若本地调试,chrome浏览器未调起摄像头权限,见下图进行配置(线上必须为https协议才可直接调起摄像头)

地址:http://chrome://flags/#unsafely-treat-insecure-origin-as-secure

②暂无其他,待补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值