JS调用摄像头拍照

927 阅读1分钟

1. 前提条件

1.1 方法一:更改http协议

  • http换成https
  • ip地址换成域名

1.2 方法二:设置浏览器信任该站点

使用谷歌内核的浏览器输入url:

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

将本地的测试域名填入,启用,重启

image.png

2. 示例代码

将下面代码保存为一个html文件,启动一个服务器访问

<!DOCTYPE html>
<html lang="ZH-CN">

<head>
    <meta charset="utf-8" />
    <title>web RTC 测试</title>
    <style>
    .face-container {
        width: 300px;
        margin: 0 auto;
        padding: 20px;
        border: 1px solid #ccc;
    }

    .face-container .face-video {
        height: 300px;
        margin: 0 auto;
    }

    .face-container .face-handle {
        display: flex;
        margin: 0 auto;
    }

    .face-btn {
        margin-top: 10px;
        border: 1px solid #f0f0f0;
        color: #fff;
        height: 36px;
        line-height: 36px;
        border-radius: 4px;
        text-align: center;
        cursor: pointer;
        cursor: pointer;
    }

    #face-btn_close {
        flex: 2;
        background: #ee5c63;
    }

    #face-btn_capture {
        flex: 3;
        background: #5cacee;
    }

    .imgBoxxx {
        width: 200px;
        margin: 60px 20px 20px;
    }
    </style>
</head>

<body>
    <div class="face-container">
        <div class="face-video">
            <video id="face-video" width="300" height="300" autoplay></video>
            <canvas style="display: none" id="face-canvas" width="300" height="300"></canvas>
        </div>
        <div class="face-handle">
            <div id="face-btn_close" class="face-btn">关闭</div>
            <div id="face-btn_capture" class="face-btn">拍照</div>
        </div>
    </div>
    <script>
    var canvas = document.getElementById('face-canvas');
    var context = canvas.getContext('2d');
    var btnCapture = document.getElementById('face-btn_capture');
    var btnClose = document.getElementById('face-btn_close');
    var video = document.getElementById('face-video');
    var mediaStreamTrack; //视频轨
    // alert('该页面会调用您的摄像头');
    // 旧版本浏览器可能根本不支持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;
            // 有些浏览器不支持,会返回错误信息
            // 保持接口一致
            if (!getUserMedia) {
                //alert("浏览器版本过旧,请升级浏览器");
                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: 400, height: 400 } };
    navigator.mediaDevices
        .getUserMedia(constraints)
        .then(function(stream) {
            var video = document.querySelector('video');
            // 旧的浏览器可能没有srcObject
            if ('srcObject' in video) {
                video.srcObject = stream;
                mediaStreamTrack = stream;
            } else {
                //避免在新的浏览器中使用它,因为它正在被弃用。
                video.src = window.URL.createObjectURL(stream);
            }
            video.onloadedmetadata = function(e) {
                video.play();
            };
        })
        .catch(function(err) {
            //alert("请检查是否正确安装摄像头设备");
            console.log(err.name + ': ' + err.message);
        });
    //拍照
    btnCapture.addEventListener('click', function() {
        // 点击,canvas画图
        context.drawImage(video, 0, 0, 300, 300);

        // canvasToBlob();
        canvasToBase64();

        //生成图片
        //方案一,画布转blob
        function canvasToBlob() {
            var onGetBlob = function(blob) {
                console.log('canvasToBlob', blob);
                var blobUrl = URL.createObjectURL(blob);

                //插入页面
                insertImgToDoc(blobUrl, function(img) {
                    // 不需要要及时释放内存
                    // img.onload = function () {
                    // 	URL.revokeObjectURL(blobUrl);
                    // };
                });

                //上传图片
                // uploadtoServer(blob);
            };
            canvas.toBlob(onGetBlob, 'image/png', 1);
        }

        //方案二,画布转base64Url

        function canvasToBase64() {
            var base64Url = canvas.toDataURL('image/png');

            //插入页面
            insertImgToDoc(base64Url, function(img) {});

            //base64Urlz转file
            var file = dataURLtoFile(base64Url, 'face.png');
            console.log('canvasToBase64ToFile', file);

            //上传图片
            // uploadtoServer(file);
        }

        //插入图片
        function insertImgToDoc(url, callback) {
            var img = new Image();
            img.src = url;
            img.className = 'imgBoxxx';
            document.body.appendChild(img);
            callback && callback(img);
        }

        //base64转file
        function 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 });
        }

        //upload file
        function uploadtoServer(file) {
            var formData = new FormData();
            formData.append('file', file);
            fetch('/fileUpload.do', {
                    method: 'post',
                    'Content-Type': 'multipart/form-data',
                    body: formData,
                })
                .then(res => res.json())
                .then(res => {})
                .catch(err => {});
        }
    });
    //关闭视频采集
    btnClose.addEventListener('click', function() {
        if (mediaStreamTrack && mediaStreamTrack.getTracks) {
            mediaStreamTrack.getTracks().forEach(it => {
                try {
                    it.stop();
                } catch (errMsg) {}
            });
        } else {
            video.pause();
            video.src = '';
        }
    });
    </script>
</body>

</html>