H5调用摄像头拍照上传

场景  h5点击唤醒手机摄像头,拍照并上传到oss

 

方案选择,在网上找了几个案例做了几个demo,首先是没有直接可以用的插件(难受😣)

 

可选方案

1、getUserMedia API

 

getUserMedia API最初是navigator.getUserMedia,目前已被最新Web标准废除,变更为navigator.mediaDevices.getUserMedia(),但浏览器支持情况不如旧版API普及。 

pc浏览器上没有问题

demo 可以直接复制查看效果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>拍照</title>
</head>
<body>
<video id="video" width="640" height="480" autoplay="autoplay"></video>
<!--拍照按钮-->
<div>
    <button id="capture">拍照</button>
</div>
<!--描绘video截图-->
<canvas id="canvas" width="640" height="480"></canvas>
<script>
    let video = document.getElementById("video");
    let canvas = document.getElementById("canvas");
    let context = canvas.getContext("2d");

    // 老的浏览器可能根本没有实现 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;

            // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口
            if (!getUserMedia) {
                return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
            }

            // 否则,为老的navigator.getUserMedia方法包裹一个Promise
            return new Promise(function (resolve, reject) {
                getUserMedia.call(navigator, constraints, resolve, reject);
            });
        }
    }

    //默认使用前摄像头,强制使用后置摄像头如下设置
    // let constraints = {video: { facingMode: { exact: "environment" } }};
    let constraints = {video: true};
    navigator.mediaDevices.getUserMedia(constraints)
        .then(function (stream) {
            // 旧的浏览器可能没有srcObject
            if ("srcObject" in video) {
                video.srcObject = stream;
            } else {
                // 防止在新的浏览器里使用它,应为它已经不再支持了
                video.src = window.URL.createObjectURL(stream);
            }
            video.onloadedmetadata = function (e) {
                video.play();
            };
        })
        .catch(function (err) {
            console.log(err.name + ": " + err.message);
        });

    //注册拍照按钮的单击事件
    document.getElementById("capture").addEventListener("click", function () {
        //绘制画面
        context.drawImage(video, 0, 0, 640, 480);
    });
</script>
</body>
</html> 

不过在手机中打开歇菜

 

 所以这个方案行不通

 

2.原生input

 

使用input标签 type值为file,可以调用系统默认的照相机、相册、摄像机、录音功能。

<input type="file" accept="image/" capture="camera">
<input type="file" accept="video/" capture="camcorder">
<input type="file" accept="audio/*" capture="microphone">

 

accept表示打开的系统文件目录
capture表示的是系统所捕获的默认设备,camera:照相机;camcorder:摄像机;microphone:录音;
其中还有一个属性multiple,支持多选,当支持多选时,multiple优先级高于capture,所以只用写成:<input type="file" accept="image/*" multiple>就可.

还有就是希望做到默认打开前置摄像头
需要设置 capture="user"  但是我写demo一直调用不到前置摄像头,我一直以为是我的使用姿势不对。。。
后来发现这个其实是安卓不支持这个属性,只有IOS支持的比较好(我晕。。。我用的安卓手机)
 
另外还有一个问题,就是我用的是react,在input中设置 capture属性,但是在浏览器审查元素,这个属性会丢失
 
所以在组件中
 
compomentDidMount里暴力塞进去
 
componentDidMount() {
    this.ifSetting()
    document.getElementsByClassName('select-video')[0].setAttribute('capture', 'user')
  }

 

完美~

 

posted @ 2020-05-25 13:58  Rachid  阅读(14653)  评论(0编辑  收藏  举报