場景 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') }