HTML5通過navigator.mediaDevices.getUserMedia調用手機攝像頭問題
文章主要介紹了HTML5通過navigator.mediaDevices.getUserMedia調用手機攝像頭問題,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下navigator.mediaDevices.getU...
文章主要介紹了HTML5通過navigator.mediaDevices.getUserMedia調用手機攝像頭問題,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
navigator.mediaDevices.getUserMedia
應項目要求,需要實現移動端app嵌入H5頁面完成實人認證的功能。打開getUserMedia文檔,鏈接如下:
https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/getUserMedia
看上去很簡單,最終卻寫的懷疑人生。
API環境
問題一:(為什么不管怎么配置都顯示前置攝像頭)
想正常使用API必須在https環境下進行,否則你會發現不管怎么寫,都只能調用默認的攝像頭(大部分都是前置,只有少部分是后置)
前端開發者可以將文件上傳至"碼云"倉庫,獲取https鏈接然后在手機上預覽
鏈接:碼云倉庫入口
根據官方文檔,目前navigator.mediaDevices.getUserMedia在ios上只支持11版本以上,且只能在safari正常運行。安卓目前沒有發現版本限制,需要兼容的代碼如下
if (navigator.mediaDevices === undefined) {
????navigator.mediaDevices = {};
?}
if (navigator.mediaDevices.getUserMedia === undefined) {
????navigator.mediaDevices.getUserMedia = function (constraints) {
????var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
????if (!getUserMedia) {
????????return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
????}
????return new Promise(function (resolve, reject) {
????????getUserMedia.call(navigator, constraints, resolve, reject);
????});
??}
}
問題三:(第一次啟用成功調用前置攝像頭,第二次需要調用后置卻黑屏或者失敗)
失敗的原因很多,列舉兩個一開始我遇到的問題
1.前置攝像頭調用后,攝像功能需要關閉后才能正常執行第二次調用,否則會報錯:設備被占用。解決方法,在每次執行調用方法前,先關閉攝像設備。
if (window.stream) {
????window.stream.getTracks().forEach(track => {
??????????track.stop();
????});
}
<
親測有用,別的找了很多停止的方法都沒有效果。
2.調用后置API的方法還是無法喚醒后置攝像頭,于是我找到另外一個方法,通過查看手機攝像頭ID,來直接喚醒后置。
var deviceInfoId="", //攝像頭ID
????num = 0, //攝像頭數量
????carema = []; //攝像頭ID數組
????//在頁面加載完成后獲得設備ID數組
window.onload = navigator.mediaDevices.enumerateDevices().then(gotDevices);
function gotDevices(deviceInfos) {
????????for (let i = 0; i < deviceInfos.length; ++i) {
????????????if (deviceInfos[i].kind === 'videoinput') {
????????????????carema.push(deviceInfos[i].deviceId)
??????????????}
????????}
????????deviceInfoId = carema[后置位置];
}
????????????var constraints = {
????????????????audio: false,
????????????????video: {
????????????????????deviceId: deviceInfoId,
????????????????????//放在app里面需要下面配置一下
????????????????????"permissions": {
????????????????????????"audio-capture": {
????????????????????????????"description": "Required to capture audio using getUserMedia()"
????????????????????????},
????????????????????????"video-capture": {
????????????????????????????"description": "Required to capture video using getUserMedia()"
????????????????????????}
????????????????????}
????????????????}
????????????};
????????????navigator.mediaDevices.getUserMedia(constraints)
????????????????.then(function (stream) {
????????????????????var video = document.getElementById('video');
????????????????????try {
????????????????????????window.stream = stream;
????????????????????????video.srcObject = stream;
????????????????????} catch (error) {
????????????????????????video.src = window.URL.createObjectURL(stream);
????????????????????}
????????????????????this.localMediaStream = stream;
????????????????????// video.play();?? 這個加不加好像沒有影響
????????????????})
????????????????.catch(function (err) {
????????????????????console.log(err.name + ": " + err.message);
????????????????});
如果只是一部手機可以這樣,但是測試了多部手機發現攝像頭數組毫無規律可循,這個方法慎用。
如果頁面上添加選擇攝像設備的按鈕的話,這個方法還是不錯的。查看設備能調用幾個攝像頭鏈接如下:https://webrtc.github.io/samples/src/content/devices/input-output/
由于我們的項目頁面不希望出現切換按鈕,面對后置出現的眾多BUG,最終選擇放棄,使用input調用攝像頭。
成功調用后用canvas實現成像并適應屏幕大小
我這里的代碼是取video的寬高然后復制給canvas,這樣可以讓canvas和video保持一致,只用給video設置寬度100%,高度調節成合適的值,就實現了適應手機屏幕。
var video = document.getElementById('video');
??????????var canvas = document.getElementById('canvas'),
??????????????ctx = canvas.getContext('2d'),
??????????????CHeight = video.clientHeight, //獲取屏幕大小讓canvas自適應
??????????????CWidth = video.clientWidth;
??????????canvas.width = CWidth;
??????????canvas.height = CHeight;
??????????//localMediaStream 在data里定義一個{}
??????????if (localMediaStream) {
??????????????ctx.drawImage(video, 0, 0, CWidth, CHeight);
??????????????var dataURL = canvas.toDataURL('image/jpeg'); //dataURL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA'
??????????????img.src = dataURL;
video成像鏡像問題
API喚醒的前置攝像頭是相反的,很不舒服很不舒服。
之后用css處理一下給video添加 transform: rotate(180deg),可以實現反轉,但是還是沒有達到和手機一樣的效果。
這時候可以選擇通過設備ID調用前置攝像頭,前置攝像頭的laval一直都是“default”,也有的是空值,但是也能實現。
配置代碼如下:
var constraints = window.constraints = {
???????????????audio: false,
???????????????video: {
???????????????????sourceId: 'default',
???????????????????facingMode:? { exact: "user" }
???????????????}
?????????????};
完美調用自己手機的前置攝像頭!!!
完整代碼如下:
頁面代碼:
<div @click='moveToCameraAVG()' v-cloak>
?????<img v-if="imginfo!==''" :src="imginfo" />
?????<div class="warm_title2">點擊自拍一張頭像</div>
</div>
<video id="video" class="pic_video" playsinline autoplay x5-video-player-type="h5" style='object-fit:fill'></video>
<canvas id="canvas" class="canvas_pic" style='margin: 0;padding: 0;'></canvas>
<div class="bottom_div">
????<div>拍照</div>
????<img src='images/pic_btn.png' class="capture-btn" @click='captureAvg' />
</div>
// 頭像相機
???????moveToCameraAVG() {
???????????var self = this;
???????????if (navigator.mediaDevices === undefined) {
???????????????navigator.mediaDevices = {};
???????????}
???????????if (navigator.mediaDevices.getUserMedia === undefined) {
???????????????navigator.mediaDevices.getUserMedia = function (constraints) {
???????????????????var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
???????????????????if (!getUserMedia) {
???????????????????????return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
???????????????????}
???????????????????return new Promise(function (resolve, reject) {
???????????????????????getUserMedia.call(navigator, constraints, resolve, reject);
???????????????????});
???????????????}
???????????}
???????????if (window.stream) {
???????????????window.stream.getTracks().forEach(track => {
???????????????????track.stop();
???????????????});
???????????}
???????????var constraints = window.constraints = {
???????????????audio: false,
???????????????video: {
???????????????????sourceId: 'default',
???????????????????facingMode:? { exact: "user" }
???????????????}
?????????????};
???????????navigator.mediaDevices.getUserMedia(constraints)
???????????????.then(function (stream) {
???????????????????var video = document.getElementById('video');
???????????????????try {
???????????????????????window.stream = stream;
???????????????????????video.srcObject = stream;
???????????????????} catch (error) {
???????????????????????video.src = window.URL.createObjectURL(stream);
???????????????????}
???????????????????self.localMediaStream = stream;
???????????????????video.play();
???????????????})
???????????????.catch(function (err) {
???????????????????alert(err.name + ": " + err.message);
???????????????});
???????},
???????//停止攝像機
???????stopCapture: function () {
???????????var video = document.getElementById('video');
???????????if (!video.srcObject) return
???????????let stream = video.srcObject
???????????let tracks = stream.getTracks();
???????????tracks.forEach(track => {
???????????????track.stop()
???????????})
???????},
???????// 頭像照片
???????captureAvg() {
???????????var vm = this;
???????????var video = document.getElementById('video');
???????????var canvas = document.getElementById('canvas'),
???????????????ctx = canvas.getContext('2d'),
???????????????CHeight = video.clientHeight, //獲取屏幕大小讓canvas自適應
???????????????CWidth = video.clientWidth;
???????????canvas.width = CWidth;
???????????canvas.height = CHeight;
???????????if (vm.localMediaStream) {
???????????????ctx.drawImage(video, 0, 0, CWidth, CHeight);
???????????????var dataURL = canvas.toDataURL('image/jpeg'); //dataURL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA'
???????????????vm.imginfo = dataURL;
???????????????// 停止攝像機
???????????????video.pause();
???????????????this.stopCapture();
???????????}
???????},
到此這篇關于HTML5通過navigator.mediaDevices.getUserMedia調用手機攝像頭問題的文章就介紹到這了,更多相關HTML5調用 攝像頭內容請搜索以前的文章或繼續瀏覽下面的相關文章
HTML5中的網絡存儲實現方式
傳統方式使用document.cookie來進行存儲,但是由于其存儲的空間只有4KB左右,并且需要復雜的操作進行解析,給發開者帶來很多不便,為此,HTML5規范提出了網絡存儲的解決方案,本文通過...
HTML5離線存儲Manifest原理及使用詳解
文章主要介紹了H5離線存儲Manifest原理及使用,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧理解:離線存儲可以將站點的文件儲存在本地,在沒有網絡...
HTML5調用手機發短信和打電話功能
文章主要介紹了HTML5調用手機發短信和打電話功能,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下前言本來感覺用H5寫調用電話撥號功能和發送短信功能會很不好寫...
HTML5標簽HTMLCollection和NodeList的區別詳解
文章主要介紹了HTML5中的HTMLCollection和NodeList的區別詳解,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧HTML5 HTMLCollection和NodeList的...
HTML5網頁中iframe與window.onload如何使用詳解
文章主要介紹了iframe與window.onload如何使用詳解,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧。前言在項目上,需要等頁面加載完之后再執行一...
HTML5網頁body設置自適應全屏示例代碼
文章主要介紹了HTML5 body設置自適應全屏,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧用什么代碼實現?不允許有白色底色產生,因為手機高度不一...
Html5 canvas中width、height和style的寬高區別詳解
文章主要給大家介紹了關于H5 canvas中width、height和style的寬高區別的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們...
一張圖看懂HTML5的前端性能優化
最近1個月一直在設計HTML5相關的產品,沒錯,主要是用于微信的,雖然很多情況下,HTML5頁面的設計類似于APP,但是由于是網頁性的東西,對移動網絡帶寬和瀏覽器性能,CPU,GP...
YouTube默認HTML5視頻播放技術 或引發流媒體視頻終端升級風暴
近日,YouTube工程總監RichardLeider發文寫道,在Chrome、IE11、Safari8和beta版Firefox瀏覽器中,YouTube已默認采用HTML5技術播放視頻。
他說,4年前YouTube開始嘗試HTML5技術,當...