需求描述:实现电脑拍照内置摄像头拍照和连接高拍仪外置摄像头拍照。

实现原理:利用H5 调用浏览器的摄像头来实现视频功能,然后利用canvas 截图,把当前的屏幕截取,生成一张图片。

注意事项:电脑有内置的摄像头,也有外接的高拍仪,所以需要获取到全部的,然后可以选择切换摄像头。

打开弹窗时会默认获取所有的摄像头,并且默认选择第一个,然后打开摄像头。点击确定时会生成一张图片。然后拿到图片就可以调取接口了。

效果如下:

以下为拍照子组件代码:

里面有一点点数据是业务数据,可自行去掉。

<template>
    <el-dialog
            width="50%"
            title="拍照"
            :before-close="closeCamera"
            :close-on-click-modal="false"
            :close-on-press-escape="false"
            :destroy-on-close="true"
            :visible.sync="innerVisible"
            append-to-body>
        <div class="camera-content">
            <el-form ref="form" :model="form" label-width="80px">
                <el-form-item label="">
                    <el-input v-model="form.eyes"></el-input>
                </el-form-item>
                <el-form-item label="">
                    <el-input v-model="form.remark"></el-input>
                </el-form-item>
                <el-form-item label="摄像头">
                    <el-select v-model="camera"
                               style="width: 100%"
                               @change="handleChange"
                               placeholder="请选择">
                        <el-option
                                v-for="item in options"
                                :key="item.value"
                                :label="item.label"
                                :value="item.value">
                        </el-option>
                    </el-select>
                </el-form-item>
            </el-form>
            <!--开启摄像头-->
            <!--        <img @click="callCamera" :src="headImgSrc" alt="摄像头">-->
            <!--                canvas截取流-->
            <canvas v-show="false" ref="canvas" width="640" height="480"></canvas>
            <!--            图片展示-->
            <video ref="video" width="640" height="480" autoplay></video>
            <!--确认-->
            <el-button size="mini" type="primary" @click="photograph">确定</el-button>
            <el-button size="mini" type="primary" @click="handleClose">关闭</el-button>
        </div>
    </el-dialog>

</template>
<script>
    export default {
        name: 'CameraUpload',
        props: {
            innerVisible: {
                type: Boolean,
                default: false,
            },
            rowData: {
                type: Object,
                default: () => {
                    return {}
                }
            }
        },
        data() {
            return {
                form: {
                    eyes: '',
                    remark: '',
                },
                headImgSrc: '',
                dialogCamera: false,
                camera: '',
                options: [],
            }
        },
        mounted() {
            // this.getAllCamera();
        },
        methods: {
            handleClose() {
                this.closeCamera();
                this.$emit('closeCamera');
            },
            handleChange(val) {
                this.closeCamera();
                this.camera = val;
                this.callCamera()
            },
            // 获取摄像头
            getAllCamera() {
                navigator.mediaDevices.enumerateDevices()
                    .then(this.gotDevices).then(this.callCamera).catch(this.handleError);
            },
            handleError(error) {
                this.$message.error(error.name + ": " + error.message)
            },
            gotDevices(deviceInfos) {
                console.log(deviceInfos);
                this.options = [];
                for (var i = 0; i < deviceInfos.length; ++i) {
                    var deviceInfo = deviceInfos[i];
                    var option = document.createElement('option');
                    option.value = deviceInfo.deviceId;
                    if (deviceInfo.kind === 'videoinput') {
                        this.options.push({
                            value: deviceInfo.deviceId,
                            label: deviceInfo.label
                        })
                    } else {
                        console.log('Found ome other kind of source/device: ', deviceInfo);
                    }
                }
                this.camera = this.options[0].value;
            },
            // 调用摄像头
            callCamera() {
                // this.getAllCamera();
                // H5调用电脑摄像头API
                navigator.mediaDevices.getUserMedia({
                    // video: true,
                    video: {
                        optional: [
                            {
                                sourceId: this.camera
                            }
                        ]
                    }
                }).then(success => {
                    console.log(success);
                    // 摄像头开启成功
                    this.$refs['video'].srcObject = success
                    // 实时拍照效果
                    this.$refs['video'].play()
                }).catch(error => {
                    this.$message.error('摄像头开启失败,请检查摄像头是否可用并重新打开!')
                })
            },
            // 拍照
            photograph() {
                let ctx = this.$refs['canvas'].getContext('2d')
                // 把当前视频帧内容渲染到canvas上
                ctx.drawImage(this.$refs['video'], 0, 0, 640, 480)
                // 转base64格式、图片格式转换、图片质量压缩
                let imgBase64 = this.$refs['canvas'].toDataURL('image/jpeg', 0.7)
                console.log(imgBase64);
                // 由字节转换为KB 判断大小
                let str = imgBase64.replace('data:image/jpeg;base64,', '')
                let strLength = str.length
                let fileLength = parseInt(strLength - (strLength / 8) * 2)
                // 图片尺寸  用于判断
                let size = (fileLength / 1024).toFixed(2)
                console.log(size)

                // 上传拍照信息  调用接口上传图片 .........
               

                // 保存到本地
                // this.dialogCamera = false
                // let ADOM = document.createElement('a')
                // ADOM.href = this.headImgSrc
                // ADOM.download = new Date().getTime() + '.jpeg'
                // ADOM.click()
            },
            // 关闭摄像头
            closeCamera() {
                if (!this.$refs['video'].srcObject) {
                    this.dialogCamera = false
                    return
                }
                let stream = this.$refs['video'].srcObject
                let tracks = stream.getTracks()
                tracks.forEach(track => {
                    track.stop()
                })
                this.$refs['video'].srcObject = null;
                // this.$emit('closeCamera')
            },
        }
    }
</script>
<style lang="less" scoped>
    .camera-content {
        text-align: center;
    }
</style>

以下为父组件引用代码:

一些业务逻辑代码可自行去掉

<CameraUpload
                :rowData="rowData"
                @closeCamera="closeCamera"
                :innerVisible="innerVisible"
                ref="myCameraUpload"/>




handleCamera() {
                this.innerVisible = true;
                this.$nextTick(() => {
                    this.$refs.myCameraUpload.getAllCamera();
                })
            },



closeCamera() {
                this.innerVisible = false;
                this.getUploadList();
            },

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐