react vr中文網(wǎng):www.vr-react.com
react vr qq群:481244084
示例源碼 github:https://github.com/LiuC520/ReactVR/
早起react 360是叫react vr的,后來facebook改成了react 360,原來的好多東西包括原理和模塊都重寫了,原來介紹了react vr 消息傳遞原理,里面有些原理已經(jīng)修改了。
現(xiàn)在我重新來倒著講一下消息傳遞的原理,這次更淺顯易懂些。
開發(fā)者頭條:react vr 原理解析
開發(fā)者頭條:React VR 視頻源碼解析
開發(fā)者頭條:react vr 消息傳遞原理解析
首先舉個(gè)例子,我想實(shí)現(xiàn)在react 一邊發(fā)送消息,在html里面能接收到,舉個(gè)例子,我要在html的入口文件中加個(gè)loading,然后在js解析完畢再關(guān)閉loading,來優(yōu)化體驗(yàn)?
??1、首先我們需要在html中添加如下的代碼:

也就是添加html5的loading div,并給了個(gè)旋轉(zhuǎn)的動(dòng)畫,只要加載頁面就顯示loading。
接下來我們來如何讓動(dòng)畫在加載了頁面以后消失。
??2、在上面html中我們可以看到,先加載的是client的bundle文件,里面有一個(gè)init的方法,然后才是具體執(zhí)行這個(gè)init初始化方法,傳遞的參數(shù)是index.bundle文件,還有要掛載的div,其他的一些配置(資源路徑等等)。
這時(shí)間我們還按照上一篇文章里講的worker來操作,因?yàn)檫@是搬運(yùn)工,來回搬運(yùn)數(shù)據(jù)的,也就相當(dāng)于快遞的中轉(zhuǎn)站。
??寄件方(劉成)把快件給了快遞員,快遞員再打個(gè)包給收件方(劉成的女朋友)。同時(shí)收件方(劉成的女朋友)也可以成為寄件方,再把新的快件給快遞員(劉成),快遞員打個(gè)包再寄回去。
??不同的是,這個(gè)快遞不一樣,里面有好多小的商品,劉成給他的女朋友買了好多東西,有牙刷、有牙膏、手機(jī)、電腦、還有西瓜,這時(shí)間快遞員就需要按照不同的類型把這些東西打包放好放到一個(gè)大箱子里面,這樣才不會(huì)亂,要不然女朋友收到這么一堆亂七八糟的東西,直接就扔了分手了。
??開個(gè)玩笑,其實(shí)react 360的消息機(jī)制就是這樣的,只不過react 360的工人跟原來的不一樣了,原來是直接聘請(qǐng)了(new)一個(gè)工人(worker),
直接在client里面調(diào)用下面的方法就可以了,具體接收到的參數(shù)就放到onVRMessage方法里面來操作
vr.rootView.context.worker.addEventListener('message',onVRMessage);//接受消息的在react vr那邊直接 postMessage({ type: "sceneLoadStart"})
function onVRMessage(e) {
switch (e.data.type) {
case 'sceneChanged':
if (window.playerCamera.zoom != 1) {
window.playerCamera.zoom = 1;
window.playerCamera.updateProjectionMatrix();
}
break;
case 'sceneLoadStart':
document.getElementById('loader').style.display = 'block';//設(shè)置html的div屬性
break;
case 'sceneLoadEnd':
document.getElementById('loader').style.display = 'none';
break;
default:
return;
}
}
//-------------------------------接受消息-e-------------------------------
而現(xiàn)在react 360重構(gòu)了以后,就好像新建一個(gè)工作站,搞了一塊兒底盤,然后建立了工作室(Executor),工人都在工作室里面
原來的工人在conext上下文中可以直接取到,現(xiàn)在需要用下面的方法才能讓loading消失。
client里面的方法如下圖

??3、運(yùn)行時(shí)
r360.runtime.executor._worker.addEventListener('message', onVRMessage);
現(xiàn)在的工人不在上下文中直接取了,
而是在運(yùn)行時(shí)里面,你也可以自己傳遞一個(gè)executor到運(yùn)行時(shí)里面,具體怎么搞,以后再給大家講解,也就是你可以自定義傳遞的類型和方法。
這個(gè)runtime是干嘛的呢?他是react vr的主要邏輯了,他發(fā)送數(shù)據(jù)給executor,在內(nèi)存中構(gòu)建node節(jié)點(diǎn),同時(shí)還告訴Compositor怎樣渲染一切的東西。
有點(diǎn)兒像CEO的感覺,總管一切,executor就像team leader,這個(gè)leader把數(shù)據(jù)包裝成blob,然后給工人去傳遞。
其他的暫時(shí)不講,至于如何在內(nèi)存中構(gòu)建node節(jié)點(diǎn),如何告訴Compositor去渲染,后面單獨(dú)開文章再講。
??4、worker
可以看到運(yùn)行時(shí)里面新建了一個(gè)ReactExecutorWebWorker,這個(gè)工人類呢里面有幾個(gè)方法,也就是team leader有幾個(gè)方法,
??4.1、首先是構(gòu)造方法,把需要的方法打包成一個(gè)Blob,里面有加載bundle的方法,有判斷是不是dev(開發(fā)環(huán)境)的方法,有發(fā)送數(shù)據(jù)的方法,有接受數(shù)據(jù)的方法,接收數(shù)據(jù)的方法,在ReactExecutor.js里面。
然后新建一個(gè)工人,工人的onmessage(接受數(shù)據(jù))方法里面會(huì)把接收到的消息放到消息隊(duì)列中,自此構(gòu)造方法結(jié)束
??4.2、moduleConfig,里面是原生的模塊(IManager、AndroidConstants、AsyncLocalStorage、ControllerInfo、History、Networking、LinkingManager、Location、Timing、VideoModule、AudioModule、WebSocketModule、ReactVRConstants、RCTExceptionsManager、RCTSourceCode、ExternalAssets、GlyphTextures)
??4.3、setConstant 設(shè)置常數(shù)
??4.4、exec 這個(gè)是發(fā)送bundle
??4.5、call 執(zhí)行方法,傳遞參數(shù)
??4.6、invoke 執(zhí)行方法,傳遞參數(shù),傳遞是是viewtag id
??4.5、flush 執(zhí)行方法,傳遞參數(shù)
上面的這寫方法都是工人發(fā)送出去的數(shù)據(jù),發(fā)送出去以后,ReactNativeContext上下文中就會(huì)一直frame,這里面會(huì)把工人的消息隊(duì)列里面的數(shù)據(jù)一條條取出來,然后只要有消息,就執(zhí)行消息
??5、發(fā)送消息,在react 一側(cè),在index.js的componentDidMount里面直接發(fā)送消息:
postMessage({type:'sceneLoadEnd'})//隱藏loading圖
具體的消息傳遞就是,view調(diào)用frame方法,渲染每一幀的方法,也就是調(diào)用了上下文的frame方法,這個(gè)方法里面就是從工人的消息隊(duì)列取數(shù)據(jù),這個(gè)數(shù)據(jù)就是上面頂一個(gè)監(jiān)聽方法,監(jiān)聽的方法渠道對(duì)應(yīng)的type,然后執(zhí)行具體的方法,就是隱藏loading。
有啥不懂得,歡迎來詢哦,QQ&微信:674668211