
React VRã©ã€ãã©ãªã䜿çšãããšã WebVR APIäžã§JavaScriptãšReactã䜿çšããŠä»®æ³çŸå®ã®Webã¢ããªã±ãŒã·ã§ã³ãäœæã§ããŸãã ãã®ä»æ§ã¯ãChromeãFirefoxãããã³Edgeãã©ãŠã¶ãŒã®ææ°ïŒå Žåã«ãã£ãŠã¯å®éšçïŒããŒãžã§ã³ã§ãµããŒããããŠããŸãã ãã®ãããVRã¡ã¬ãã¯å¿
èŠãããŸããã
WebVR Experimentsã¯ã WebVRã®æ©èœã瀺ãã·ã§ãŒã±ãŒã¹ãµã€ãã§ãã ç§ã®æ³šç®ã¯ã Mozilla VRããŒã ã«ãã£ãŠéçºãããWebVRã®Webãã¬ãŒã ã¯ãŒã¯ã§ããA-Frameã䜿çšããGoogle Creative Labã®çŽ æŽããã人ã«ãã£ãŠäœæããããããžã§ã¯ãThe Musical Forestã«åŒãä»ããããŸããã
Musical Forestã§ã¯ãWebSocketã®ãããã§ããŠãŒã¶ãŒã¯å¹ŸäœåŠçå³åœ¢ãã¯ãªãã¯ããããšã§ãªã¢ã«ã¿ã€ã ã§äžç·ã«é³æ¥œãåçã§ããŸãã ãããã䜿çšå¯èœãªæ©èœãšæè¡ã䜿çšãããŠãããããã¢ããªã±ãŒã·ã§ã³ã¯éåžžã«è€éã§ããïŒ ãœãŒã¹ã³ãŒã ïŒã ã§ã¯ãããã·ã£ãŒããŒã¹ã®ãã«ããŠãŒã¶ãŒãµããŒãã䜿çšããŠãReact VRã§åæ§ã®ãªã¢ã«ã¿ã€ã ã¢ããªã±ãŒã·ã§ã³ãäœæããŠã¿ãŸãããïŒ
React VR / Pusherã®ããŒãžã§ã³ã¯æ¬¡ã®ãšããã§ãã
ãŠãŒã¶ãŒã¯ãURLã«ãã£ãã«èå¥åãå
¥åã§ããŸãã 3次å
ã®å³åœ¢ãã¯ãªãã¯ãããšããµãŠã³ããåçãããããã·ã£ãŒã€ãã³ããçºè¡ãããŸããããã¯ãåããã£ã³ãã«ã®ä»ã®ãŠãŒã¶ãŒãåããµãŠã³ããåä¿¡ããŠââèããã®ã§ãã
ã€ãã³ããå
¬éããã«ã¯ãNode.jsããã¯ãšã³ãã䜿çšãããããJavaScriptãšReactã®çµéšãå¿
èŠã§ãã React VRãšVRã§äœ¿çšãããæŠå¿µãåããŠäœ¿çšããå Žåã¯ããŸããã®èšäºãã芧ãã ããã
ããŠã³ããŒããªã³ã¯ïŒè©ŠããŠã¿ãŠãã ããïŒïŒ
â React VRãããžã§ã¯ã ã
â Node.jsããã¯ãšã³ã ã
VRãããžã§ã¯ããã»ããã¢ãããã
React VR CLIããŒã«ãã€ã³ã¹ããŒã«ïŒãŸãã¯æŽæ°ïŒããããšããå§ããŸãããã
npm install -g react-vr-cli
æ°ããReact VRãããžã§ã¯ããäœæããŸãã
react-vr init musical-exp-react-vr-pusher
圌ãäœæãããã£ã¬ã¯ããªã«ç§»åããã³ãã³ããå®è¡ããŠéçºãµãŒããŒãèµ·åããŸãã
cd musical-exp-react-vr-pusher npm start
ãã©ãŠã¶ã§ãã¢ãã¬ã¹httpïŒ// localhostïŒ8081 / vr /ã«ç§»åããŸãã ããã衚瀺ãããŸãïŒ

äºææ§ã®ãããã©ãŠã¶ãŒïŒWindowsçFirefox Nightlyãªã©ïŒã䜿çšããŠããå Žåã¯ã [VRã§è¡šç€º]ãã¿ã³ã衚瀺ãããŸããããã«ãããVRã¡ã¬ãã§ã¢ããªã±ãŒã·ã§ã³ã衚瀺ã§ããŸãã

ããã°ã©ãã³ã°ã«ç§»ããŸãããã
èæ¯ãäœæãã
èæ¯ãšããŠã æ£è·åç峿³ãèŠãŠã¿ãŸãããã ãã®ãããªç»åã®äž»ãªç¹åŸŽã¯ãå¹
ãé«ãã®ã¡ããã©2åã§ããããšã§ãã ãæ°ã«å
¥ãã®ã°ã©ãã£ãã¯ãšãã£ã¿ãŒãéãã4096Ã2048ã®ã°ã©ããŒã·ã§ã³å¡ãã€ã¶ãç»åãäœæããŸãã ããªãã®å¥œã¿ã®è²ã

ã¢ããªã±ãŒã·ã§ã³ã«ãŒãã®static_assetsãã£ã¬ã¯ããªå
ã§ãæ°ããç»åãã©ã«ããäœæããããã«ç»åãä¿åããŸãã index.vr.jsãã¡ã€ã«ãéããrenderã¡ãœããã®ã³ã³ãã³ããæ¬¡ã®ããã«çœ®ãæããŸãã
render() { return ( <View> <Pano source={asset('images/background.jpg')} /> </View> ); }
ããŒãžããªããŒãïŒãŸãã¯ããããªããŒããã¢ã¯ãã£ãåïŒ ãããš ãæ¬¡ã®ããã«è¡šç€ºãããŸãã

ããªãŒããšãã¥ã¬ãŒãããã«ã¯ã Cylinderã䜿çšããŸãã å®éããŠãŒã¶ãŒã®åšå²ã«æ£®æã確ä¿ããã«ã¯100人ãå¿
èŠã§ãã ãã¡ã€ã«js / components / background-objects.jsã®å
ã®Musical Forestã§ã¯ãããªãŒãçæããã¢ã«ãŽãªãºã ãèŠã€ããããšãã§ããŸãã ã³ãŒãããããžã§ã¯ãã®Reactã³ã³ããŒãã³ãã«é©å¿ããããšã次ã®ããã«ãªããŸãã
import React from 'react'; import { View, Cylinder, } from 'react-vr'; export default ({trees, perimeter, colors}) => { const DEG2RAD = Math.PI / 180; return ( <View> {Array.apply(null, {length: trees}).map((obj, index) => { const theta = DEG2RAD * (index / trees) * 360; const randomSeed = Math.random(); const treeDistance = randomSeed * 5 + perimeter; const treeColor = Math.floor(randomSeed * 3); const x = Math.cos(theta) * treeDistance; const z = Math.sin(theta) * treeDistance; return ( <Cylinder key={index} radiusTop={0.3} radiusBottom={0.3} dimHeight={10} segments={10} style={{ color: colors[treeColor], opacity: randomSeed, transform: [{scaleY : 2 + Math.random()}, {translate: [x, 3, z]},], }} /> ); })} </View> ); }
æ©èœã³ã³ããŒãã³ãã¯3ã€ã®ãã©ã¡ãŒã¿ãŒãåããŸãã
trees
ãã©ã¬ã¹ãå
ã§ååŸããå¿
èŠãããæšã®æ°ãperimeter
-ãŠãŒã¶ãŒããã¬ã³ããªã³ã°ããªãŒã®ç¯å²ãå¶åŸ¡ã§ããå€colors
æšã®è²ã®å€ã®é
åã
Array.apply(null, {length: trees})
ã䜿çšãããšã空ã®å€ã®é
åãäœæã§ããŸããããã«ããã颿°ãé©çšããŠã Viewã³ã³ããŒãã³ãå
ã®ã©ã³ãã ãªè²ãéæåºŠãäœçœ®ã®åæ±ã®é
åãæç»ããŸãã
ã³ã³ããŒãã³ããã£ã¬ã¯ããªå
ã®Forest.jsãã¡ã€ã«ã«ã³ãŒããä¿åããindex.vr.jså
ã§äœ¿çšã§ããŸãã
... import Forest from './components/Forest'; export default class musical_exp_react_vr_pusher extends React.Component { render() { return ( <View> <Pano source={asset('images/background.jpg')} /> <Forest trees={100} perimeter={15} colors={['#016549', '#87b926', '#b1c96b']} /> </View> ); } }; ...
ããã¯ãã©ãŠã¶ã«è¡šç€ºãããŸãã ããŠãèæ¯ã®æºåãã§ããŸããããµãŠã³ããäœæãã3Dãªããžã§ã¯ããäœæããŸãã
6ã€ã®3Dãã©ãŒã ãäœæããå¿
èŠããããŸããããããã«ã¿ãããããšã6ã€ã®ç°ãªããµãŠã³ããåçãããŸãã å°ããªã¢ãã¡ãŒã·ã§ã³ã¯ãã«ãŒãœã«ããªããžã§ã¯ãã«é
眮ãããããªããžã§ã¯ãããåé€ããããããšãã«ã圹ç«ã¡ãŸãã
ãã©ãŒã ãäœæããã«ã¯ã VrButton ã Animated.View ã Box ã Cylinderããã³Sphereãå¿
èŠã§ãã ãã ãããã¹ãŠã®ãã©ãŒã ã¯ç°ãªããããã³ã³ããŒãã³ããã«ãã»ã«åããã ããªã®ã§ãåãã«ãªããŸãã æ¬¡ã®ã³ãŒããcomponents / SoundShape.jsãã¡ã€ã«ã«ä¿åããŸãã
import React from 'react'; import { VrButton, Animated, } from 'react-vr'; export default class SoundShape extends React.Component { constructor(props) { super(props); this.state = { bounceValue: new Animated.Value(0), }; } animateEnter() { Animated.spring( this.state.bounceValue, { toValue: 1, friction: 4, } ).start(); } animateExit() { Animated.timing( this.state.bounceValue, { toValue: 0, duration: 50, } ).start(); } render() { return ( <Animated.View style={{ transform: [ {rotateX: this.state.bounceValue}, ], }} > <VrButton onEnter={()=>this.animateEnter()} onExit={()=>this.animateExit()} > {this.props.children} </VrButton> </Animated.View> ); } };
ã«ãŒãœã«ããã¿ã³é åã«å
¥ããšã Animated.spring
ã¯this.state.bounceValue
ã®å€ã0ãã1ã«å€æŽããè·³ãè¿ã广ã瀺ããŸãã ã«ãŒãœã«ããã¿ã³é åããé¢ãããšã Animated.timing
ã¯this.state.bounceValue
ã®å€ã50ããªç§é1ãã0ã«å€æŽããŸãã ãããæ©èœããããã«ã VrButton
ãAnimated.View
ã³ã³ããŒãã³ãã«ã©ããããŸããããã«ãããç¶æ
ã倿Žããããã³ã«ãã¥ãŒã®rotateX倿ã倿ŽãããŸãã
SpotLight
ãSpotLight
远å ãïŒä»ã®ã¿ã€ãã®å
æºãéžæããŠãã®ããããã£ã倿Žã§ããŸãïŒã SoundShape
ã³ã³ããŒãã³ãã䜿çšããŠãã·ãªã³ããŒãäœæSoundShape
ãŸãã
... import { AppRegistry, asset, Pano, SpotLight, View, Cylinder, } from 'react-vr'; import Forest from './components/Forest'; import SoundShape from './components/SoundShape'; export default class musical_exp_react_vr_pusher extends React.Component { render() { return ( <View> ... <SpotLight intensity={1} style={{transform: [{translate: [1, 4, 4]}],}} /> <SoundShape> <Cylinder radiusTop={0.2} radiusBottom={0.2} dimHeight={0.3} segments={8} lit={true} style={{ color: '#96ff00', transform: [{translate: [-1.5,-0.2,-2]}, {rotateX: 30}], }} /> </SoundShape> </View> ); } }; ...
ãã¡ããã3Dãã©ãŒã ã®ããããã£ã倿Žãããã 3Dã¢ãã«ã«çœ®ãæãããããããšãã§ããŸã ã
次ã«ããã©ãããïŒååŸãŒããååŸ4ã»ã°ã¡ã³ãã®åæ±ïŒã远å ããŸãã
<SoundShape> <Cylinder radiusTop={0} radiusBottom={0.2} dimHeight={0.3} segments={4} lit={true} style={{ color: '#96de4e', transform: [{translate: [-1,-0.5,-2]}, {rotateX: 30}], }} /> </SoundShape>
ãã¥ãŒãïŒ
<SoundShape> <Box dimWidth={0.2} dimDepth={0.2} dimHeight={0.2} lit={true} style={{ color: '#a0da90', transform: [{translate: [-0.5,-0.5,-2]}, {rotateX: 30}], }} /> </SoundShape>
å¹³è¡å
é¢äœïŒ
<SoundShape> <Box dimWidth={0.4} dimDepth={0.2} dimHeight={0.2} lit={true} style={{ color: '#b7dd60', transform: [{translate: [0,-0.5,-2]}, {rotateX: 30}], }} /> </SoundShape>
ç¯å²ïŒ
<SoundShape> <Sphere radius={0.15} widthSegments={20} heightSegments={12} lit={true} style={{ color: '#cee030', transform: [{translate: [0.5,-0.5,-2]}, {rotateX: 30}], }} /> </SoundShape>
ãããŠäžè§æ±ïŒ
<SoundShape> <Cylinder radiusTop={0.2} radiusBottom={0.2} dimHeight={0.3} segments={3} lit={true} style={{ color: '#e6e200', transform: [{translate: [1,-0.2,-2]}, {rotateX: 30}], }} /> </SoundShape>
ã€ã³ããŒãåŸããã¡ã€ã«ãä¿åããŠãã©ãŠã¶ãŒãæŽæ°ããŸãã ããã倿ããã¯ãã§ãïŒ

ãµãŠã³ãã远å ããŠãã ããïŒ
é³ã远å ãã
ãšããããReact VRã¯wavãmp3ãoggãã¡ã€ã«ããµããŒãããŠããŸãã å®å
šãªãªã¹ãã¯ãã¡ãã§ãã
FreesoundãŸãã¯å¥ã®åæ§ã®ãµã€ããããµã³ãã«ãååŸã§ããŸãã 奜ããªãã®ãããŠã³ããŒãããŠããã£ã¬ã¯ããªã«static_assets / soundsã眮ããŠãã ããã ãã®ãããžã§ã¯ãã§ã¯ã é³¥ ã å¥ã®é³¥ ã å¥ã®é³¥ ã ç« ã ç¬ ã ã¯ãªã±ããã®6å¹ã®åç©ã®é³ãåããŸãïŒãããã¬ãŒããäžããã«ã¯æåŸã®ãã¡ã€ã«ãä¿åããå¿
èŠããããŸããããããªããšãReact VRã¯åçããŸããïŒã
React VRã«ã¯ããµãŠã³ããåçããããã®3ã€ã®ãªãã·ã§ã³ããããŸãã
ãã ãã3D /ãµã©ãŠã³ããµãŠã³ãã¯Sound
ã³ã³ããŒãã³ãã®ã¿ããµããŒãããŠããããããªã¹ããŒãã¹ããŒãžäžãç§»åãããšããé ãåãããšãã«å·Šå³ã®ãã£ã³ãã«ã®ãã©ã³ã¹ãå€åããŸãã SoundShape
ã®onClick
ã€ãã³ãã®ããã«ã SoundShape
ã³ã³ããŒãã³ãã«è¿œå ãVrButton
ã
... import { ... Sound, } from 'react-vr'; export default class SoundShape extends React.Component { ... render() { return ( <Animated.View ... > <VrButton onClick={() => this.props.onClick()} ... > ... </VrButton> <Sound playerState={this.props.playerState} source={this.props.sound} /> </Animated.View> ); } }
åçãå¶åŸ¡ããã«ã¯ã MediaPlayerStateã䜿çšããŸã ã ãããã¯ã³ã³ããŒãã³ãã®ããããã£ãšããŠæž¡ãããŸãã
index.vr.jsããã®æ
å ±ã䜿çšããŠãé
åãå®çŸ©ããŸãã
... import { ... MediaPlayerState, } from 'react-vr'; ... export default class musical_exp_react_vr_pusher extends React.Component { constructor(props) { super(props); this.config = [ {sound: asset('sounds/bird.wav'), playerState: new MediaPlayerState({})}, {sound: asset('sounds/bird2.wav'), playerState: new MediaPlayerState({})}, {sound: asset('sounds/bird3.wav'), playerState: new MediaPlayerState({})}, {sound: asset('sounds/cat.wav'), playerState: new MediaPlayerState({})}, {sound: asset('sounds/cricket.wav'), playerState: new MediaPlayerState({})}, {sound: asset('sounds/dog.wav'), playerState: new MediaPlayerState({})}, ]; } ... } And a method to play a sound using the MediaPlayerState object when the right index is passed: ... export default class musical_exp_react_vr_pusher extends React.Component { ... onShapeClicked(index) { this.config[index].playerState.play(); } ... }
ãã®ãã¹ãŠã®æ
å ±ãSoundShapeã³ã³ããŒãã³ãã«è»¢éããã ãã§ãã 3Dãã©ãŒã ãé
åã«ã°ã«ãŒãåããããã颿°ã䜿çšããŠã³ã³ããŒãã³ããçæããŸãã
... export default class musical_exp_react_vr_pusher extends React.Component { ... render() { const shapes = [ <Cylinder ... />, <Cylinder ... />, <Box ... />, <Box ... />, <Sphere ... />, <Cylinder ... /> ]; return ( <View> ... {shapes.map((shape, index) => { return ( <SoundShape onClick={() => this.onShapeClicked(index)} sound={this.config[index].sound} playerState={this.config[index].playerState}> {shape} </SoundShape> ); })} </View> ); } ... }
ãã©ãŠã¶ãåèµ·åãããªããžã§ã¯ããã¯ãªãã¯ããŠã¿ãŠãã ãããç°ãªãé³ãèãããŸãã
ããã·ã£ãŒã䜿çšããŠããªã¢ã«ã¿ã€ã ã®ãã«ããŠãŒã¶ãŒãµããŒããReact VRã¢ããªã±ãŒã·ã§ã³ã«è¿œå ããŸãã
ããã·ã£ãŒãã«ã¹ã¿ãã€ãºãã
https://pusher.com/signupã§ç¡æã®ã¢ã«ãŠã³ããäœæããŸã ã ã¢ããªã±ãŒã·ã§ã³ãäœæãããšãäœããæ§æããããã«æ±ããããŸãã

ååãå
¥åããããã³ããšã³ããšããŠReactãéžæããããã¯ãšã³ããšããŠNode.jsãéžæããŸã å§ããããã®ã³ãŒãäŸïŒ

å¿é
ããå¿
èŠã¯ãããŸãããç¹å®ã®ãã¯ãããžãŒã»ããã«åºå·ããå¿
èŠã¯ãããŸããããã€ã§ã倿Žã§ããŸãã ã©ã€ãã©ãªã®ä»»æã®çµã¿åãããPusherã§äœ¿çšã§ããŸãã
ã¯ã©ã¹ã¿ãŒIDïŒãã®äŸã§ã¯mt1ã®ã¢ããªã±ãŒã·ã§ã³åã®åŸã«ãããŸãïŒãã¢ããªã±ãŒã·ã§ã³IDãããŒãããã³ç§å¯æ
å ±ãã³ããŒããŸãããããã¯å¿
èŠã§ãã ããã¯ãã¹ãŠã[ ã¢ããªã㌠]ã¿ãã§ã確èªã§ããŸãã
ã€ãã³ããå
Ž
React VRã¯Web Workerã®ããã«æ©èœããŸã ïŒ ãããªã® React VRã¢ãŒããã¯ãã£ã®è©³çްïŒããã®ãããindex.vr.jsã«Pusher workerã¹ã¯ãªãããå«ããå¿
èŠããããŸãã
... importScripts('https://js.pusher.com/4.1/pusher.worker.min.js'); export default class musical_exp_react_vr_pusher extends React.Component { ... }
æºãããªããã°ãªããªã2ã€ã®æ¡ä»¶ããããŸãã æåã«ãURLãä»ããŠèå¥åãæž¡ãããšãã§ããå¿
èŠããããŸãïŒ httpïŒ// localhostïŒ8081 / vr /ïŒChannel = 1234ã®ããã« ïŒããŠãŒã¶ãŒã¯ã©ã®ãã£ã³ãã«ã«è¡ããå人ãšå
±æããããéžæã§ããŸãã
ãããè¡ãã«ã¯ãURLãèªã¿åãå¿
èŠããããŸãã 幞ããªããšã«ãReact VRã«ã¯ãwindow.locationãªããžã§ã¯ãã®ããããã£ãReactã³ã³ããã¹ãã§äœ¿çšã§ããããã«ãããã€ãã£ãã® Location ã¢ãžã¥ãŒã«ãä»å±ããŠããŸãã
次ã«ãæ¥ç¶ãããŠãããã¹ãŠã®ã¯ã©ã€ã¢ã³ããã€ãã³ããåçã§ããããã«ãããã·ã£ãŒã€ãã³ããçºè¡ãããµãŒããŒã«æ¥ç¶ããå¿
èŠããããŸãã ãã ããã€ãã³ããçæããã¯ã©ã€ã¢ã³ããåä¿¡ããå¿
èŠã¯ãããŸããããã®å ŽåããµãŠã³ãã2ååçãããããã§ãã ãããŠããŠãŒã¶ãŒããªããžã§ã¯ããã¯ãªãã¯ãããšããã«ãã€ãã³ãããµãŠã³ããåçããã®ãåŸ
ã€ãã€ã³ãã¯äœã§ããïŒ
åããã·ã£ãŒæ¥ç¶ã«ã¯ãäžæã®ãœã±ããIDãå²ãåœãŠãããŸãã åä¿¡è
ãããã·ã£ãŒã§ã€ãã³ããåä¿¡ã§ããªãããã«ããã«ã¯ãã€ãã³ããçºçãããšãã«é€å€ããã¯ã©ã€ã¢ã³ããsocket_id
ãµãŒããŒã«è»¢éããå¿
èŠããããŸãïŒè©³çްã¯ãã¡ã ïŒã
ãããã£ãŠãããã·ã£ãŒã«æ£åžžã«æ¥ç¶ãããšãã«getParameterByName
颿°ããããã«èª¿æŽããŠURLãã©ã¡ãŒã¿ãŒãèªã¿åã ã socketId
ãä¿åããããšã§ãäž¡æ¹ã®èŠä»¶ã確èªã§ããŸãã
... import { ... NativeModules, } from 'react-vr'; ... const Location = NativeModules.Location; export default class musical_exp_react_vr_pusher extends React.Component { componentWillMount() { const pusher = new Pusher('<INSERT_PUSHER_APP_KEY>', { cluster: '<INSERT_PUSHER_APP_CLUSTER>', encrypted: true, }); this.socketId = null; pusher.connection.bind('connected', () => { this.socketId = pusher.connection.socket_id; }); this.channelName = 'channel-' + this.getChannelId(); const channel = pusher.subscribe(this.channelName); channel.bind('sound_played', (data) => { this.config[data.index].playerState.play(); }); } getChannelId() { let channel = this.getParameterByName('channel', Location.href); if(!channel) { channel = 0; } return channel; } getParameterByName(name, url) { const regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); const results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, " ")); } ... }
URLã«ãã£ãã«ãã©ã¡ãŒã¿ããªãå Žåãããã©ã«ãã§ID 0ãå²ãåœãŠããããã®IDã¯ããã·ã£ãŒãã£ãã«ã«è¿œå ãããŠäžæã«ãªããŸãã
æåŸã«ãã€ãã³ããå
¬éãããµãŒããŒåŽã§ãšã³ããã€ã³ããåŒã³åºãå¿
èŠããããã¯ã©ã€ã¢ã³ããœã±ããIDãšã€ãã³ããå
¬éããããã£ãã«ãæž¡ããŸãã
... export default class musical_exp_react_vr_pusher extends React.Component { ... onShapeClicked(index) { this.config[index].playerState.play(); fetch('http://<INSERT_YOUR_SERVER_URL>/pusher/trigger', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ index: index, socketId: this.socketId, channelName: this.channelName, }) }); } ... }
ReactããŒãã®ã³ãŒãã¯ããã§ãã¹ãŠã§ãã æ¬¡ã«ããµãŒããŒãææ¡ããŸãããã
Node.jsããã¯ãšã³ããäœæãã
ã³ãã³ãã䜿çšããŠãpackage.jsonãã¡ã€ã«ãçæããŸãã
npm init -y
äŸåé¢ä¿ã远å ããŸãã
npm install
ãããŠããã®ã³ãŒãããã¡ã€ã«ã«ä¿åããŸãã
const express = require('express'); const bodyParser = require('body-parser'); const Pusher = require('pusher'); const app = express(); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use((req, res, next) => { res.header("Access-Control-Allow-Origin", "*") res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept") next(); }); const pusher = new Pusher({ appId: '<INSERT_PUSHER_APP_ID>', key: '<INSERT_PUSHER_APP_KEY>', secret: '<INSERT_PUSHER_APP_SECRET>', cluster: '<INSERT_PUSHER_APP_CLUSTER>', encrypted: true, }); app.post('/pusher/trigger', function(req, res) { pusher.trigger(req.body.channelName, 'sound_played', { index: req.body.index }, req.body.socketId ); res.send('ok'); }); const port = process.env.PORT || 5000; app.listen(port, () => console.log(`Running on port ${port}`));
ã芧ã®ãšãããExpressãµãŒããŒãPusherãªããžã§ã¯ããããã³ã«ãŒã/ããã·ã£ãŒ/ããªã¬ãŒãèšå®ããŸãããããã¯ãåçãããµãŠã³ãã€ã³ããã¯ã¹ãšãã€ãã³ãã¬ã·ãŒããŒãé€å€ããsocketIDãæã€ã€ãã³ããçºçãããã ãã§ãã
ãã¹ãŠæºåå®äºã§ãã ãã¹ãããŠã¿ãŸãããã
ãã¹ãäž
次ã®ã³ãã³ãã§Node.jsããã¯ãšã³ããå®è¡ããŸãã
node server.js
index.vr.jsã§ãµãŒããŒã®URLãæŽæ°ãïŒlocalhostã®ä»£ããã«IPã䜿çšïŒã2ã€ã®ãã©ãŠã¶ãŒãŠã£ã³ããŠã§httpïŒ// localhostïŒ8081 / vr /ïŒChannel = 1234ã®ãããªã¢ãã¬ã¹ãéããŸãã 3Dãã©ãŒã ãã¯ãªãã¯ãããšã2ååçãããé³ãèãããŸãïŒããã¯ãç°ãªãã³ã³ãã¥ãŒã¿ãŒäžã®å人ãšäžç·ã«è¡ãæ¹ãã¯ããã«æ¥œããã§ãïŒã
ãããã«
React VRã¯ãç¹ã«React / React Nativeããã§ã«ç¥ã£ãŠããå Žåã¯ç¹ã«ãVRãããžã§ã¯ããç°¡åã«äœæã§ããåªããã©ã€ãã©ãªã§ãã ããã«ããã·ã£ãŒã远å ãããšã匷åãªæ°äžä»£ã®Webã¢ããªã±ãŒã·ã§ã³éçºã³ã³ãã¬ãã¯ã¹ãåŸãããŸãã
ä»»æã®WebãµãŒããŒã«ãããã€ããããã«ããã®ãããžã§ã¯ãã®è£œåãªãªãŒã¹ãã³ã³ãã€ã«ã§ããŸãïŒ https : //facebook.imtqy.com/react-vr/docs/publishing.html
ãŸããè²ã圢ãé³ã倿Žãããããªãªãžãã«ã®ãã¥ãŒãžã«ã«ãã©ã¬ã¹ãã®æ©èœã远å ãããããããšãã§ããŸãã
GitHubãªããžããªãããããžã§ã¯ãã³ãŒããããŠã³ããŒãã§ããŸãã