摘要:快速入門什么是是一個開放源代碼的庫,為呈現的數據提供了視圖渲染。最后,項目根組件應該通過來進行注冊,以便能夠進行打包和正常運行。基本思想是渲染一個立方體,并將觀眾置于中心,隨后移動。表示從指定方向平均照亮所有物體的光源。
React VR 快速入門 什么是React
React是一個開放源代碼的JavaScript庫,為HTML呈現的數據提供了視圖渲染。React視圖通常使用指定的像HTML標簽一樣的組件來進行UI渲染。它目前是最流行的JavaScript庫之一,它擁有強大的基礎和龐大的社區。
創建一個React App$ npm install -g create-react-app $ create-react-app my-app $ cd my-app $ npm start效果圖 什么是React Native?
React Native是僅使用Javascript的移動應用構建框架。它使用與React相同的設計,包含豐富的UI庫和組件聲明。
它使用與常規iOS和Android應用程序相同的基本UI構建塊。
使用React-Native最贊的地方是還可以通過原生的Objective-C, Java, 或者Swift來構建組件。
React VS React Native:
React Native bridge:
創建一個React Native App環境安裝
查看官網http://facebook.github.io/react-native/docs/getting-started.html
創建項目
$ react-native init my-rn-app
運行項目
To run your app on iOS: cd /Users/liyuechun/Pictures/my_rn_app react-native run-ios - or - Open ios/my_rn_app.xcodeproj in Xcode Hit the Run button To run your app on Android: cd /Users/liyuechun/Pictures/my_rn_app Have an Android emulator running (quickest way to get started), or a device connected react-native run-android
效果圖
iOS | Android |
---|---|
React VR旨在允許Web開發人員使用React的聲明方法(特別是React Native)來創作虛擬現實(VR)應用程序。
React VR使用Three.js 來支持較低級別的WebVR 和 WebGL API. WebVR是用于訪問Web上VR設備的API。 WebGL(Web圖形庫)是一種無需使用插件即可用于在任何兼容的Web瀏覽器中渲染3D圖形的API。
React VR類似于React Native,因為它使用View,Image和Text作為核心組件,并且支持Flexbox布局。 此外,React VR還將Pano,Mesh和PointLight等VR組件添加相關庫中。
在本篇文章中,我將帶領大家創建一個簡單的VR應用程序來學習如何創建一個全景圖片,3D對象模型,按鈕和flexbox布局的使用場景。我們的模擬應用程序基于React VR的兩個網格和布局的官方示例。
該應用程序將渲染一個能夠放大和縮小的地球和月球的3D模型,效果圖如下所示:
這些模型中,它們的尺度和旋轉不是地球-月球系統的真實復制品。 這種關系只是為了展示React VR的工作原理。 與此同時,我們將解釋一些關鍵的3D建模概念。 一旦掌握了ReactVR,就可以隨意創造更多的作品。
你能夠從 GitHub找到最后的項目源代碼。
要求到目前為止,虛擬現實是一項相當新的技術,開發或測試我們的VR應用程序的方法很少。
WebVR 和 Is WebVR Ready? 可以幫助您了解哪些瀏覽器和設備支持最新的VR規范。
但是你也不必過于擔心, 你現在不需要任何特殊的設備,例如: Oculus Rift, HTC Vive, 或者 Samsung Gear VR 來測試一個WebVR APP。
下面是你現在 所需要 準備的:
一臺Windows/Mac電腦。
Google瀏覽器。
最新版本的Node.js
如果您也有Android設備和Gear VR耳機,您可以安裝Carmel Developer Preview瀏覽器來探索您的React VR 應用程序。
創建項目首先,我們需要使用NPM來安裝React VR CLI工具:
$ npm install -g react-vr-cli
使用React VR CLI來創建一個名字叫做EarthMoonVR的新項目:
$ react-vr init EarthMoonVR
在創建過程中您需要等一會兒,這將創建一個EarthMoonVR目錄,目錄里面就是相關項目文件,如果希望創建速度快一些,您可以安裝 Yarn 來提高速度。
一旦項目創建完畢,可以通過cd切換到EarthMoonVR文件路徑下面:
$ cd EarthMoonVR
在終端通過npm start來啟動程序以便查看效果:
$ npm start
在瀏覽器中輸入http://localhost:8081/vr。稍微等一會兒,即可查看到VR效果:
下面是初始化的React VR新項目的項目結構:
+-__tests__ +-node_modules +-static_assets +-vr -.babelrc -.flowconfig -.gitignore -.watchmanconfig -index.vr.js -package.json -rn-cli-config.js -yarn.lock
我將index.vr.js文件呈現高亮狀態,它包含了您應用程序的源碼,static_assets目錄包含像圖片和3D模型的外部資源文件。
你可以從這里了解更多項目結構。
index.vr.js 文件的內容如下:
import React from "react"; import { AppRegistry, asset, StyleSheet, Pano, Text, View, } from "react-vr"; class EarthMoonVR extends React.Component { render() { return (); } }; AppRegistry.registerComponent("EarthMoonVR", () => EarthMoonVR); hello
我們可以看到React VR使用了ES2015 和 JSX。
這個代碼通過React Native packager進行預編譯,它提供了(ES2015, JSX)編譯和其他資源加載。
在render函數中,return了一個頂級標簽,里面包含:
View 組件, 它是可以包含其他所有組件的容器組件。
Pano 組件, 用于將(chess-world.jpg)渲染一張360度的圖片。
Text 組件, 用于渲染字體的3D空間。
注意,Text組件通過一個內聯的樣式對象來設置樣式。在React VR中的每一個組件都有一個style屬性來控制控制它的外觀和布局。
除了添加Pano或VrButton等特殊組件之外,React VR還使用了與React和React Native相同的概念,例如組件,屬性,狀態,生命周期,事件和彈性布局。
最后,項目根組件應該通過AppRegistry.registerComponent來進行注冊,以便App能夠進行打包和正常運行。
現在我們知道代碼是做什么用的,接下來我們將全景圖片拖拽到項目中。
全景圖像通常,我們的VR應用程序中的空間由全景(pano)圖像組成,它創建了一個1000米的球體(在React VR距離中,尺寸單位為米),并將用戶置于其中心。
一張全景圖像允許你從上面,下面,后面以及你的前面去觀察它,這就是他們也被稱為360的圖像或球面全景的原因。
360全景圖有兩種主要格式:平面全景圖和立方體。 React VR支持兩者。
平面全景圖平面全景圖由寬高比為2:1的單個圖像組成,意味著寬度必須是高度的兩倍。
這些照片是通過360度照相機創建的。一個很好的平面圖像來源是Flickr,你打開這個網站嘗試搜索equirectangular關鍵字,例如:我通過equirectangular關鍵字嘗試搜索就找到這張圖片:
看起來很奇怪,不是嗎?
無論如何,下載最高可用分辨率的照片,將其拖拽到項目中static_assets的路徑下面,并且修改render函數中的代碼,如下所示:
render() { return (); }
Pano組件的source屬性接收一個當前圖片位置的uri屬性值。這里我們使用了asset函數,將sample_pano.jpg作為參數,這個函數將會返回static_assets 路徑下的圖片的正確的uri。換句話說,上面的方法等價于下面的方法:
render() { return (); }
假設本地服務器一直在運行,當我們在瀏覽器中刷新頁面時,我們將看到如下效果:
順便說一下,如果我們想避免在每次更改時都需要重新刷新頁面,我們可以通過在URL(http://localhost:8081/vr/?hot... 中添加 ?hotreload 來啟用 熱刷新。
立方體全景圖立方體全景圖是360度全景圖的其他格式。這種格式使用六個圖像作為一個多維數組集的六個面,它將填充我們周圍的球體。 它也被稱為天空盒。
基本思想是渲染一個立方體,并將觀眾置于中心,隨后移動。
例如,下面的這張大圖中,每一個方位的小圖代表立方體的一面:
為了能夠在React VR中使用立方體全景圖,Pano組件的source屬性的uri值必須指定為一個數組,數組中的每一張圖片分別代表[+x, -x, +y, -y, +z, -z],如下所示:
render() { return (); }
在2D布局中,X軸越向右x值越大,Y軸越向下值越大,(0,0)坐標為最左上角,右下角代表元素的寬和高(width, height)。
然而,在3D空間中,React VR使用了同OpenGL使用的右手坐標系統,正X指向右邊,正Y指向上邊,正Z指向用戶的方向。因為用戶的默認視圖從原點開始,這意味著它們將從負Z方向開始:
你可以從React VR coordinate system here了解更多React VR坐標系統.
這樣,我們的立方體(或天空盒)將如下所示:
Skybox在Unity中使用了很多,所以有很多地方可以找到他們并進行下載。 例如,我從這個頁面下載了撒哈拉沙漠。我將圖片拖拽到項目中,并修改代碼如下所示:
render() { return (); }
效果如下所示:
你能注意到頂部和底部的圖像不協調嗎?我們可以通過將頂部圖像順時針旋轉90度,底部逆時針旋轉90度來校正它們:
現在讓我們為我們的應用創建一個空間天空盒。
最好的程序是Spacescape, 它一個免費的工具,可在Windows和Mac上創建空間天空盒(包括星星和星云)。
創建一個sampleSpace.xml文件,將下面的代碼拷貝到sampleSpace.xml文件中:
one 0 0 0 1 1 1 false 0.5 2 fbm 1 1 1 1 1 0 Fuzzy Blue Stars 1 1 1 1 3000 3 4 one points one 0.03 1.5 1 1 1 1 1 1 2 Fuzzy White Star Overlay ridged 8 0.94 0 0 0 1 1 1024 10 4 0.81 one noise
并且通過Spacescape軟件打開sampleSpace.xml文件,效果圖如下所示:
我們可以導出天空盒的六張圖像:
如果我們修改代碼如下所示:
將得到如下結果:
現在讓我們來討論討論3D模型。
聯系我 3D 模型React VR 有一個 Model 組件,它支持Wavefront .obj file format 來代表3D建模。
mesh是定義3D對象形狀的頂點、邊和面的集合。
.obj文件是一個純文本文件,其中包含幾何頂點,紋理坐標,頂點法線和多邊形面元素的坐標。
通常,.obj文件引用一個外部.mtl file文件,其中存儲了描述多邊形視覺方面的材質(或紋理)。
您可以使用Blender, 3DS Max,和Maya等程序創建3D模型并將其導出為這些格式。
還有很多網站可以免費下載或免費下載3D模型。 以下是其中三個很不錯的:
TF3DM
TurboSquid
CGTrader
對于我們的應用程序,我們將使用這個3D地球模型和這個來自TF3DM的3D月球模型 。
當我們將地球模型的文件提取到我們應用程序的static_assets目錄時,我們可以看到有一堆圖像(紋理)以及.obj和.mtl文件。 如果我們在文本編輯器中打開后者,我們將看到如下所示定義:
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware # File Created: 25.01.2016 02:22:51 newmtl 01___Default Ns 10.0000 Ni 1.5000 d 1.0000 Tr 0.0000 Tf 1.0000 1.0000 1.0000 illum 2 Ka 0.0000 0.0000 0.0000 Kd 0.0000 0.0000 0.0000 Ks 0.0000 0.0000 0.0000 Ke 0.0000 0.0000 0.0000 map_Ka 4096_earth.jpg map_Kd 4096_earth.jpg map_Ke 4096_night_lights.jpg map_bump 4096_bump.jpg bump 4096_bump.jpg newmtl 02___Default Ns 10.0000 Ni 1.5000 d 1.0000 Tr 0.0000 Tf 1.0000 1.0000 1.0000 illum 2 Ka 0.5882 0.5882 0.5882 Kd 0.5882 0.5882 0.5882 Ks 0.0000 0.0000 0.0000 Ke 0.0000 0.0000 0.0000 map_Ka 4096_earth.jpg map_Kd 4096_earth.jpg map_d 4096_earth.jpg
現在我們將添加Model組件,如下面的代碼所示:
lit屬性指定網格中使用的材料應使用Phong shading處理燈。
同時,也不要忘了從react-vr中導入Model組件:
import { ... Model, } from "react-vr";
但是,如果我們只將該組件添加到我們的應用程序中,則不會顯示任何內容。 我們首先需要添加一個光源。
React VR 有四種光源類型:
AmbientLight表示全方位,固定強度和固定顏色的光源,可以均勻地影響場景中的所有對象。
DirectionalLight表示從指定方向平均照亮所有物體的光源。
PointLight 代表光的起源來源于一個點,并向各個方向傳播。
SpotLight 代表光的起源來源于一個點,并以錐形向外擴散。
您可以嘗試所有類型的燈光,看看哪一個可以為您帶來最佳效果。 在這種情況下,我們將使用強度值為2.6的AmbientLight:
import React from "react"; import { AppRegistry, asset, StyleSheet, Pano, Text, View, Model, AmbientLight, } from "react-vr"; class EarthMoonVR extends React.Component { render() { return (... ); } }; AppRegistry.registerComponent("EarthMoonVR", () => EarthMoonVR);
接下來,我們需要給我們的模型一些用于放置、大小、和旋轉的樣式屬性。 通過嘗試不同的值,我想出了以下配置:
class EarthMoonVR extends React.Component { render() { return (... ); } }; AppRegistry.registerComponent("EarthMoonVR", () => EarthMoonVR);
Transforms被表示為一個樣式對象中的對象數組,請記住它們最后被應用的單位是米。
translate將您的模型的位置轉換為x,y,z空間,scale給您的模型一個大小,并根據提供的度數繞軸旋轉。
這是效果圖:
這個地球模型可以應用多個紋理。 默認情況下它帶 clouds 紋理,但是我們可以通過用4096_earth.jpg替換最后三行中的4096_clouds.jpg來更改.mtl文件中的內容:
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware # File Created: 25.01.2016 02:22:51 newmtl 01___Default ... newmtl 02___Default ... map_Ka 4096_earth.jpg map_Kd 4096_earth.jpg map_d 4096_earth.jpg
效果圖如下:
順便說一下,如果您的模型不帶有.mtl文件,React VR允許您通過下面的代碼指定紋理:
我們對月球模型做同樣的操作,將紋理的路徑修復到.mtl文件中,并嘗試使用不同的比例和放置值。 您不需要添加另一個光源,AmbientLight將適用于兩種模型。
這是我想出的月球模型的代碼:
render() { return (... ); }
效果圖:
如果你想在WebVR上下文中了解更多關于360度全景圖的信息,你可以查看the developer documentation at Oculus這篇文章。
現在,我們一起來為模型添加動畫。
模型動畫化React VR 有一個 動畫庫來以簡單的方式組合一些類型的動畫。
在這個時候,只有幾個組件可以自己動畫(View 使用 Animated.View, Text 使用 Animated.Text, Image 使用 Animated.Image). 這個文檔 提醒你可以通過createAnimatedComponent來創建更多的動畫,但是目前為止還找不到更多的相關信息。
另位一種選擇是使用requestAnimationFrame , 它是基于JavaScript動畫API的重要組成部分。
那么我們可以做的就是要有一個狀態屬性來表示兩個模型的Y軸上的旋轉值(在月球模型上,為了使它變慢讓旋轉是地球旋轉的三分之一):
class EarthMoonVR extends React.Component { constructor() { super(); this.state = { rotation: 130, }; } render() { return (... ); } };
現在我們來編寫一個rotate函數,它將通過requestAnimationFrame函數調用每一幀,在一定時間基礎上更新旋轉:
class EarthMoonVR extends React.Component { constructor() { super(); this.state = { rotation: 130, }; this.lastUpdate = Date.now(); this.rotate = this.rotate.bind(this); } rotate() { const now = Date.now(); const delta = now - this.lastUpdate; this.lastUpdate = now; this.setState({ rotation: this.state.rotation + delta / 150 }); this.frameHandle = requestAnimationFrame(this.rotate); } ... }
幻數 150只是控制旋轉速度(這個數字越大,旋轉速度越慢)。 我們保存由requestAnimationFrame返回的處理程序,以便當組件卸載并啟動componentDidMount上的旋轉動畫時,我們可以取消動畫:
class EarthMoonVR extends React.Component { constructor() { super(); this.state = { rotation: 130, }; this.lastUpdate = Date.now(); this.rotate = this.rotate.bind(this); } componentDidMount() { this.rotate(); } componentWillUnmount() { if (this.frameHandle) { cancelAnimationFrame(this.frameHandle); this.frameHandle = null; } } rotate() { const now = Date.now(); const delta = now - this.lastUpdate; this.lastUpdate = now; this.setState({ rotation: this.state.rotation + delta / 150 }); this.frameHandle = requestAnimationFrame(this.rotate); } ... }
這是效果圖(你可能沒有注意到,但是月亮旋轉得很慢):
現在讓我們來添加一些button來增加一些交互。
添加button并設置樣式為我們的button創建一個新的組件。在實際開發中,我們也能使用View 或者VrButton,這倆都能設置像onEnter一樣的有效的事件來達到我們的目的。
然而,我們將使用VrButton,因為它有和其他組件不一樣的狀態機,并且很方便的添加onClick 和 onLongClick事件。
同時,我們為了讓button外觀更好看一些,我們將使用StyleSheet 來創建一個樣式對象,并通過一個樣式ID來對button進行引用。
下面是button.js的內容:
import React from "react"; import { StyleSheet, Text, VrButton, } from "react-vr"; export default class Button extends React.Component { constructor() { super(); this.styles = StyleSheet.create({ button: { margin: 0.05, height: 0.4, backgroundColor: "red", }, text: { fontSize: 0.3, textAlign: "center", }, }); } render() { return (this.props.callback()}> ); } }{this.props.text}
一個VrButton沒有外觀效果,因此我們必須給它添加樣式。它也可以包裝一個Image或Text組件。當點擊這個button時,我們可以給它傳遞一個事件函數來接收點擊事件。
現在在我們的根組件中,我們倒入Button 組件并且在render函數中,如下所示添加兩個Button。
... import Button from "./button.js"; class EarthMoonVR extends React.Component { ... render() { return (... ); } };...
這兩個Button在被觸發時將會改變模型的Z坐標值并進行相應的縮放。因此,我們添加一個zoom狀態機變量值,讓它的初始值為-70(地球的Z軸值),當我們點擊+和-時會增加和減少 zoom的值。
class EarthMoonVR extends React.Component { constructor() { super(); this.state = { rotation: 130, zoom: -70, }; ... } render() { return (... ); } };
現在我們通過StyleSheet.create來給包含兩個Button的View添加flexbox布局樣式。
class EarthMoonVR extends React.Component { constructor() { super(); ... this.styles = StyleSheet.create({ menu: { flex: 1, flexDirection: "column", width: 1, alignItems: "stretch", transform: [{translate: [2, 2, -5]}], }, }); ... } render() { return (... ); } };... this.setState((prevState) => ({ zoom: prevState.zoom + 10 }) ) } /> this.setState((prevState) => ({ zoom: prevState.zoom - 10 }) ) } />
在flexbox布局中,子組件會通過flexDirection:"column"屬性值垂直布局,通過flexDirection:"row"屬性值水平布局。在這個案例中,flex設置為1代表兩個button大小一樣,flexDirection設置為column代表兩個button從上往下排列。alignItems的值為stretch代表兩個Button和父視圖寬度一樣。
看看 this page on the React Native documentation 和 this one on the React VR documentation 這兩篇文章來了解更多關于flexbox布局的相關知識。
最后,我們可以從render函數中將天空盒的圖片移除,以便render中的代碼看起來不至于那么擁擠:
import React from "react"; import { AppRegistry, asset, StyleSheet, Pano, Text, View, Model, AmbientLight, } from "react-vr"; import Button from "./button.js"; class EarthMoonVR extends React.Component { constructor() { super(); this.state = { rotation: 130, zoom: -70, }; this.lastUpdate = Date.now(); this.spaceSkymap = [ "../static_assets/space_right.png", "../static_assets/space_left.png", "../static_assets/space_up.png", "../static_assets/space_down.png", "../static_assets/space_back.png", "../static_assets/space_front.png" ]; this.styles = StyleSheet.create({ menu: { flex: 1, flexDirection: "column", width: 1, alignItems: "stretch", transform: [{translate: [2, 2, -5]}], }, }); this.rotate = this.rotate.bind(this); } componentDidMount() { this.rotate(); } componentWillUnmount() { if (this.frameHandle) { cancelAnimationFrame(this.frameHandle); this.frameHandle = null; } } rotate() { const now = Date.now(); const delta = now - this.lastUpdate; this.lastUpdate = now; this.setState({ rotation: this.state.rotation + delta / 150 }); this.frameHandle = requestAnimationFrame(this.rotate); } render() { return (); } }; AppRegistry.registerComponent("EarthMoonVR", () => EarthMoonVR); this.setState((prevState) => ({ zoom: prevState.zoom + 10 }) ) } /> this.setState((prevState) => ({ zoom: prevState.zoom - 10 }) ) } />
如果我們測試這個應用程序,我們將看到兩個button均觸發了相關事件。
總結React Native 是基于React的一個移動端的JavaScrpit庫,而React VR又是基于React Native的適用于虛擬現實的JavaScrpit庫。React VR允許我們快速方便的創建VR體驗。
有很多相關的社區,如A-Frame和React VR 中文網。如果你想在App中制作360度的VR全景效果,并且如果你了解React/React Native,那么React VR是非常不錯的選擇。
記住,你能夠從GitHub下載本篇文章中的源碼。
謝謝閱讀!
社群品牌:從零到壹全棧部落
定位:尋找共好,共同學習,持續輸出全棧技術社群
業界榮譽:IT界的邏輯思維
文化:輸出是最好的學習方式
官方公眾號:全棧部落
社群發起人:春哥(從零到壹創始人,交流微信:liyc1215)
技術交流社區:全棧部落BBS
全棧部落完整系列教程:全棧部落完整電子書學習筆記
關注全棧部落官方公眾號,每晚十點接收系列原創技術推送 |
---|
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/83450.html
摘要:新聞熱點國內國外,前端最新動態發布近日,正式發布新版本中提供了一系列的特性與問題修復。而近日正式發布,其能夠幫助開發者快速構建應用。 前端每周清單第 10 期:Firefox53、React VR發布、JS測試技術概述、Microsoft Edge現代DOM樹構建及性能之道 為InfoQ中文站特供稿件,首發地址為這里;如需轉載,請與InfoQ中文站聯系。從屬于筆者的 Web 前端入門...
摘要:前端每周清單半年盤點之與篇前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點分為新聞熱點開發教程工程實踐深度閱讀開源項目巔峰人生等欄目。與求同存異近日,宣布將的構建工具由遷移到,引發了很多開發者的討論。 前端每周清單半年盤點之 React 與 ReactNative 篇 前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點;分為...
摘要:新聞熱點國內國外,前端最新動態就開源許可證風波進行回復數周前,基金會決定禁止旗下項目使用,因為其在標準的許可證之外添加了專利聲明此舉引發了社區的廣泛討論,希望能夠更新其開源許可證。 showImg(https://segmentfault.com/img/remote/1460000010777089); 前端每周清單第 27 期:React Patent License 回復,Sho...
摘要:新聞開發者研習會與的研習會開發者研習會于日開始,本次的開發者研習會中與相關的主題有兩個,分別是與相關,視頻已放在網絡上可觀看。是用于創建數據導向的應用的框架,主要使用了與這兩項技術。如果您對內容有疑問,請到新聞網站或庫關注我們。 新聞 F8開發者研習會與React 2017的F8研習會(Facebook開發者研習會)于4/18日開始,本次的開發者研習會中與React相關的主題有兩個,分...
閱讀 1958·2021-11-16 11:45
閱讀 3668·2021-09-06 15:02
閱讀 2013·2019-08-30 15:44
閱讀 2282·2019-08-30 11:21
閱讀 1845·2019-08-29 16:31
閱讀 3421·2019-08-29 13:55
閱讀 1894·2019-08-29 12:15
閱讀 3251·2019-08-28 18:05