天津網站制作|天津網站制作公司|天津網站設計|天津網站設計公司-龍禧科技十五年匠心設計, 未來觸手可及。

咨詢電話:022-588 36597

北京網站制作之—網頁前端設計也能做的AR互動

發布時間:2017-09-19    瀏覽次數:

  目錄

 
一、項目體驗
二、技術實現
三、兼容情況
四、遇到的問題
五、結語
 
 
正文

 
一、項目體驗
 
    以往的AR,都是要在某個APP內才可以體驗到的,例如pokemon go和QQ AR火炬傳遞活動。

\\

 
     我們團隊在做技術儲備的時候,發現Android設備下微信、手Q支持getUserMedia()網頁拉起攝像頭,并通過createObjectURL把數據流傳給video在頁面展示,以營造出實時視頻的效果。據最新統計數據顯示,安卓操作系統占有全球移動智能手機系統86.2%的市場份額。也就是說,我們可以基于微信和手Q來做網頁的AR互動啦!!!(http://digi.tech.qq.com/a/20160822/034526.htm?t=1471877263208)
于是我們基于實際需求發起并開發了一個WebAR的H5項目,玩家進來頁面可以在不安裝額外APP的情況下,體驗到AR帶來的樂趣;針對不支持實時視頻的瀏覽器,就提供3D全景體驗版。進入頁面根據提示操作即可完成WebAR小游戲,跳轉落地頁。

\   

\  \

 
 
二、技術實現
 
2.1 WebRTC——WebAR的基礎
 
     無論是APPAR還是WebAR的一個最基礎要實現的功能就是實時視頻效果。WebRTC(網頁實時通信,Web Real-Time Communication)是一個支持網頁瀏覽器進行實時語音對話或視頻對話的API。getUserMedia()是WebRTC的其中一個API,就是支持網頁拉起攝像頭的API,攝像頭獲取到的數據流會以<video>標簽作為載體呈現在頁面上,這就給了我們一個很好的信息,可以在video上疊加任何我們需要的內容和操作,從而營造出WebAR的效果。
 
關鍵代碼:
function getMedia() { 
 if (navigator.getUserMedia) { 
 navigator.getUserMedia({ 
 'video': { 
 'optional': [{ 
 }] 
 }
 }, successFunc, errorFunc); 
 } 
 else { 
 alert('Native device media streaming (getUserMedia) not supported in this browser.'); 
 }
} 
var localStream;
function successFunc(stream) { 
 document.getElementById('video').src = window.URL && window.URL.createObjectURL(stream) || stream;
 localStream = stream; 
} 
function errorFunc(e) { 
 alert('Error!'+e); 
} 
function closeMedia() { 
 localStream.stop();
 document.getElementById('video').src = '';
}

 (http://blog.csdn.net/journey191/article/details/40744015)

 
2.2 3D模型——WebGL、three.js、3DMAX
 
    這次做的WebAR非常酷炫的一個體驗是他的3D模型展示。要在網頁展示3D模型,需要先把模型放到3DMAX里進行預處理(過程會遇到很多bug和困難),導出成js文件,再借助three.js在頁面里建立模型、調整動畫等(過程也會遇到很多bug和困難)。這塊工作主要是四姑娘(signhuang)來負責的,讓我們期待四姑娘后面更詳細心酸的分享吧。
 
2.3 3D全景——three.js、球體全景
 
    3D全景的制作有很多種方法,CSS3、Flash、Krpano等,因為3D模型動畫我們是借助three.js在頁面建模的,所以3D全景我們也考慮用three.js來制作。
 
 
三、兼容情況
 
3.1 getUserMedia()
 
     由于蘋果的安全機制問題,iOS設備任何瀏覽器都不支持getUserMedia()。
     最終數據展示,Android設備下,有99.45%的設備在微信是支持getUserMedia()的,98.05%的設備在手Q是支持getUserMedia()的。而我們之前測試機型里面,本機瀏覽器、QQ瀏覽器對getUserMedia()都有不同程度的支持。
     2015年底前,也就是chrome47版本前,chrome是支持http頁面拉起攝像頭的,出于安全問題考慮,chrome47版本后只支持https頁面拉起攝像頭。

\

(http://caniuse.mojijs.com/Home/Html/item/key/stream/index.html)
 
3.2 3D模型&3D全景
 
     WebGL是一項利用JavaScript API渲染交互式3D電腦圖形和2D圖形的技術,可兼容任何的網頁瀏覽器,無需加裝插件。WebGL在現代瀏覽器中已經被廣泛支持。3D模型在移動設備瀏覽器上的兼容情況還是很好的,已測試機型里面,92%的設備是支持瀏覽器3D建模和動畫的。

\

(http://caniuse.mojijs.com/Home/Html/item/key/webgl/index.html)
 
 
四、遇到的問題
 
4.1 getusermedia()
 
4.1.1 前后攝像頭
遇到問題:
      使用getUserMedia()拉起攝像頭時,默認是拉起前置攝像頭的,但是要營造WebAR的效果,肯定是需要拉起后置攝像頭的。
 
解決方法:
      因為在獲取設備源ID的時候,前置攝像頭會排在后置攝像頭前,不單獨設置的話,就會使用第一個獲取到的設備源ID,也就是前置攝像頭的ID。稍微增加點預處理即可。
 
關鍵代碼:
var exArray = []; //存儲設備源ID 
if (navigator.getUserMedia) { 
 MediaStreamTrack.getSources(function (sourceInfos) { 
 for (var i = 0; i != sourceInfos.length; ++i) { 
 var sourceInfo = sourceInfos[i]; 
 //這里會遍歷audio,video,所以要加以區分 
 if (sourceInfo.kind === 'video') { 
 exArray.push(sourceInfo.id); 
 } 
 }
 navigator.getUserMedia({ 
 'video': { 
 'optional': [{ 
 'sourceId': exArray[1] //0為前置攝像頭,1為后置 
 }] 
 },
 'audio':false 
 }, successFunc, errorFunc); 
 });
}

 

4.1.2 攝像頭全屏
遇到問題:
    攝像頭拍攝的內容不能完美的全屏,上下總有留白,不完美。嘗試了多種原生設置來設置<video>大小,希望能完美鋪滿全屏,然而都不成功。
 
解決方法:
     上圖是用CSS設置了<video>為紅色背景,并且設置了寬高鋪滿全屏。<video>標簽確實如期待的展現,但攝像頭拍攝到的內容卻不會被合理鋪滿全屏。可以理解為就像我們平常拍攝的視頻,是有固定寬高比的,在瀏覽器寬高比不同又要求視頻全部顯示時,就會出現上下留白或者左右留白的情況。測試發現,<video>標簽不需要另外設置寬高,會默認為鋪滿全屏并且溢出,那我們在外層增加一個div并且設置為瀏覽器寬高,再增加 overflow:hidden就可以模擬全屏的效果了。

\    \

 
關鍵代碼:
<style>
#videoBox{position: absolute;left: 50%;top: 50%;z-index: 1;-webkit-transform: translate(-50%,-50%);-webkit-transform-origin: 50% 50%;}
#videoWrap{position: relative;left: 0;top: 0;background: #4CAABE;overflow: hidden;}
</style>
<div id="videoWrap">
 <video autoplay="autoplay" id="videoBox"></video>
</div>
<script>
var videoWrap = document.getElementById('videoWrap');
videoWrap.style.width = window.innerWidth + 'px';
videoWrap.style.height = window.innerHeight + 'px';
</script>
 
4.1.3 頁面無法針對模型點擊
遇到問題:
    本來頁面設置的是讓用戶點擊3D模型來進行交互的,可發現沒辦法單獨點擊到模型,整個交互就不能進行下去了。
 
解決方法:
      修改了頁面的點擊交互方式,改用坐標瞄準判定的方式。頁面中心設置一個瞄準區域,用戶移動手機讓3D模型處在瞄準區域內,即判定為成功,進行下一步。這樣就避免了頁面需要點擊的情況。
     思路是:3D模型和camera都有自己的三維坐標,new THREE.Vector3獲取到兩者的坐標,a.angleTo(b)求他們的夾角,夾角小于設定范圍,則判斷為已瞄準。
      由于最開始的需求是要做一個tips,提醒用戶向左轉或者向右轉,用的是new THREE.Vector2獲取到兩者在Y面的坐標,再用a.angle()-b.angle()求得兩者在Y面的夾角來判斷當前camera在模型的右側還是左側。新需求相當于要增加上下的判定,用new THREE.Vector2獲取到兩者在X面的坐標,再用a.angle()-b.angle()求得兩者在X面的夾角。Y面夾角和X面夾角都小于設定范圍時,則判斷為已瞄準。
 

\

 
關鍵代碼:
/***瞄準判定***/
var v = camera.getWorldDirection();
//左右判斷
var a1 = new THREE.Vector2( a.position.x, a.position.z );
var b1 = new THREE.Vector2( v.x, v.z );
dt1 = a1.angle()-b1.angle();
//上下判斷
var a2 = new THREE.Vector2( a.position.y, a.position.z );
var b2 = new THREE.Vector2( v.y, v.z );
dt2 = a2.angle()-b2.angle();
if(Math.abs(dt1)<0.1 && Math.abs(dt2)<0.1){
 //居中啦!
}

 

4.2 3D全景
 
4.2.1 iOS和Android初始化3D全景的朝向不一致
遇到問題:
    iOS設備在任何朝向(東南西北)打開3D全景,都是看向一個固定方向的。

\

 
    Android設備在不同朝向(東南西北)打開3D全景,看向的是不同方向。

\

 
    這個頁面為了降低交互難度以及固定讓3D模型出現在舞臺上(背景比較好看),需要的是在不同朝向(東南西北)打開3D全景,都是看向一個固定方向的。
 
解決方法:
      頁面加載完畢初始化camera,獲取到camera看向的矢量(不會根據看向角度不同而不同),lookAt(target)旋轉3D全景朝向那個位置,這樣每次打開頁面都會朝向一個固定的方向,再rotate各個方向進行最終調整。
 
關鍵代碼:
var v = camera.getWorldDirection();
var geometry = new THREE.SphereGeometry( 1000, 16, 8 );
 geometry.scale( -1, 1, 1 );
var material = new THREE.MeshBasicMaterial( {
 map: new THREE.TextureLoader().load( 'bg.jpg' )
} );
var stage = new THREE.Mesh( geometry, material );
stage.lookAt(new THREE.Vector3( v.x, 0, v.z ));
stage.rotateY((85 * Math.PI)/180);
stage.rotateZ((-4 * Math.PI)/180);
scene.add( stage );

 

4.2.2 初始化定位
遇到問題:
    用戶進入頁面時候的手機角度有各種情況,可能是豎著手機掃描二維碼,然后平放手機等待加載完成查看頁面。頁面初始化方向和最終查看方向差太多的話,渲染的全景、3D模型等的位置可能會偏移很大。
 
解決方法:
    進入頁面捕獲camera看向的矢量,加載完成捕獲當前camera看向的矢量,有偏移的話重新初始化全景、3D模型等的位置和角度。
 
關鍵代碼:
if(!hasMoved && typeof(defaultCameraDirection)!='undefined'){
 var v = camera.getWorldDirection();
 if( v.x != defaultCameraDirection.x
 || v.y != defaultCameraDirection.y
 || v.z != defaultCameraDirection.z
 ){
 hasMoved = true;
 resetLocationAndRotation();//初始化
 }
}

 

4.3 不支持情況排除
 
4.3.1 getUserMedia()、three.js、陀螺儀
 
①判斷是否支持getUserMedia()
function getMedia() { 
 if (navigator.getUserMedia) { 
 }, successFunc, errorFunc);//errorFunc是設備支持getUserMedia但是用戶不同意調用攝像頭的情況
 } 
 else { 
 //設備不支持getUserMedia
 }
} 
function errorFunc(e) { 
 alert('Error!'+e); 
}

 

②用Detector.js判斷是否支持WebGL
<script src="https://github.com/mrdoob/three.js/blob/master/examples/js/Detector.js"></script>
<script>
if(!Detector.webgl) {
 //不支持WebGL
}else{
 //支持WebGL
}
</script>

 

③使用three.js有報錯時
console.error = (function(origin){ 
 return function(errorlog) {
 if(/THREE/.test(errorlog)) {
 //Three報錯
 }
 } 
})(console.error);
console.warn = (function(origin){ 
 return function(errorlog) {
 if(/^THREE.WebGLRenderer:$/.test(errorlog)) {
 //Three渲染時報錯
 }
 } 
})(console.warn);

 

④設備不支持陀螺儀
if(window.DeviceOrientationEvent) {
 //支持陀螺儀
}else{
 //不支持陀螺儀
}

 

4.3.2 iOS8未知錯誤
遇到問題:
      有位遠方的同事是iPhone 5S,測試發現加載到100%了,加載界面一直不消失,頁面卡住。
 
解決方法:
      本身頁面的設置是:為了防止加載界面隱藏后,3D全景和3D模型沒渲染完成顯示一片空白,于是加了個判定,建模渲染完成才隱藏加載界面。找身邊的同事借了iPhone 5S測試,能順利進入3D全景AR界面,所以不是設備問題。問了下微信版本也是最新的,系統版本是iOS8,而沒有問題的iPhone 5S的系統版本是iOS9,所以考慮是系統版本導致的問題。但是設備不在身邊沒辦法一步步排除可能性,查了下iOS8的占比只有2.8%,該游戲用戶群體iOS設備占比少于30%,所以決定放棄這部分用戶的頁面體驗,直接跳轉落地頁。
 
關鍵代碼:
var agent = navigator.userAgent.toLowerCase() ;
var version;
if(agent.indexOf("like mac os x") > 0){
 //ios
 var regStr_saf = /os [\d._]*/gi ;
 var verinfo = agent.match(regStr_saf) ;
 version = (verinfo+"").replace(/[^0-9|_.]/ig,"").replace(/_/ig,".");
}
var version_str = version+"";
if(version_str != "undefined" && version_str.length >0){
 version=version.substring(0,1);
 if(version>5 && version <9){
 //版本為iOS8以下直接跳轉落地頁
 }
}

 

 
五、結語

 

做新技術研究和實踐的過程中會遇到沒有先例的坑,去查API文檔,曲線救國的方式解決問題(有時候覺得重構/前端是一個需要帶著小聰明的工種XD)。很感謝游戲公眾號的同事們給予的大力支持讓我們的頁面能順利上線并被推送給玩家,看著數據蹭蹭蹭的漲,終于覺得努力沒有白費了。

最終頁面的數據展示出,部分用戶設備是支持拉起攝像頭的,但可能出于安全問題的考慮,他們拒絕拉起。這是我們后續工作要考慮的一個問題,如何保護用戶隱私以及讓用戶信任我們。

總的來說,這是一次很有趣充實的新技術研究和實踐,學習的過程是很讓人幸福的。

JDB夺宝电子下载 粤海七星彩高手料论坛 内蒙古11选5走势图一定牛网 山东十一选五及时开奖 福彩开奖历史记录表 体山东时时 nba 球探网即时比分 北京赛车开奖直播 北京赛记录直播 竞彩足球历史数据 千炮捕鱼电玩城 三分赛结果 广东十一选五前一推荐号 软件时时彩 山东时时玩法规则 新平台电子送免费彩金不限id bet365体育博彩开户