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表示的是系统所捕获的默认设备,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') }