What is React 360?
React 360 is a framework used for creating 3D and VR interfaces built on top of React allowing you to use familiar tools and concepts to create immersive 360 content on the web.
What We’ll Be Building
In this Tutorial we will be exploring how to setup React 360 and implement some basic functionality and interaction to create a scrollable 360 degree gallery featuring Van Gogh’s paintings that users can explore.
Prerequisite Knowledge / Requirements
- React
- JavaScript
- You will need Node installed on your computer as we will be using NPM (Node Package Manager) to install React 360 and it’s dependencies.
Installing React 360 and Setup of Project Files
First you are going to need to install the React 360 library as well as dependencies using NPM, so create a folder for your project and run the following terminal command:
npm install -g react-360-cli
Next we want to initiate a new project and call it slideshow (or whatever you wish to call the project) and run the following command in the terminal to create a new react 360 project in your folder.
react-360 init slideshow
OK, now finally to install the dependencies and start the project locally type:
npm install
npm start
This should now boot up the page on your local machine at http://localhost:8081/index.html, so open up that address and you should see the default project loading up in your browser.
Prepare and Load Assets
Now we want to load the images we want to present to the user, so we need to locate the folder in our freshly created React 360 project to add the images to – so find some appropriate images you want to load into your project and put them into the static_assets folder for use in your app.
Load Images
Next logically we are going to want to load these assets in for use in our app, which we do in the client.js file in our project. We want to edit the array of props which is passed to the application and add our own images* , open up client.js and paste the following code into it:
*Caveat – if you are using different images in your static_assets folder you will have to load the paths to those images instead of those listed in the code below!
import {ReactInstance} from 'react-360-web'; function init(bundle, parent, options = {}) { const r360 = new ReactInstance(bundle, parent, { fullScreen: true, ...options, }); r360.renderToSurface( r360.createRoot('Slideshow', { photos: [ {uri: './static_assets/selfportrait.jpg', title: 'Self Portrait', format: '2D'}, {uri: './static_assets/stars.jpg', title: 'Starry Night', format: '2D'}, {uri: './static_assets/sunflowers.jpg', title: 'Sunflowers', format: '2D'}, // Add your own 180 / 360 photos to this array, // with an associated title and format ], }), r360.getDefaultSurface(), ); } window.React360 = {init};
Create the Slider Interface for the Application
Next we are going to want to create the slider interface itself as well as define the applications functionality which we can do by editing index.js. The following code takes a state object, stores the index of the current photo as well as rendering two buttons which either increase or decrease the index position. Have a look below and see if you understand then paste this into your index.js file before moving onto the next part.
import React from 'react'; import { AppRegistry, Environment, StyleSheet, Text, View, VrButton, } from 'react-360'; class Background extends React.Component { constructor(props) { super(); Environment.setBackgroundImage(props.uri, {format: props.format}); } componentWillReceiveProps(nextProps) { if ( nextProps.uri !== this.props.uri || nextProps.format !== this.props.format ) { Environment.setBackgroundImage(nextProps.uri, {format: nextProps.format}); } } render() { return null; } } class Slideshow extends React.Component { state = { index: 0, }; _prevPhoto = () => { let next = this.state.index - 1; if (next < 0) { next += this.props.photos.length; } this.setState({ index: next, }); }; _nextPhoto = () => { this.setState({ index: this.state.index + 1, }); };
This creates the functionality to slide for our slideshow as well as resetting the background image, but we still need to build our users interface so we are going to want to add the following code in index.js in it’s render() method.
This adds the components we require for the user to interact with a slider as well as defining some styles for these components stored in a const variable called style.
render() { const current = this.props.photos[ this.state.index % this.props.photos.length ]; return ( <View style={styles.wrapper}> <Background uri={current.uri} format={current.format} /> <View style={styles.controls}> <Text style={styles.TitleText}>Van Gogh 3D Slider</Text> <VrButton onClick={this._prevPhoto} style={styles.button}> <Text style={styles.buttonText}>{'<'}</Text> </VrButton> <View> <Text style={styles.title}>{current.title}</Text> </View> <VrButton onClick={this._nextPhoto} style={styles.button}> <Text style={styles.buttonText}>{'>'}</Text> </VrButton> </View> </View> ); } } const styles = StyleSheet.create({ wrapper: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', height: 600, width: 1000, }, controls: { backgroundColor: 'rgba(0, 0, 0, 0.7)', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', width: 600, padding: 10, }, title: { color: '#ffffff', textAlign: 'left', fontSize: 36, fontWeight: 'bold', }, button: { backgroundColor: '#c0c0d0', borderRadius: 5, width: 40, height: 44, }, buttonText: { textAlign: 'center', color: '#000000', fontSize: 30, fontWeight: 'bold', }, TitleText: { textAlign: 'center', color: '#ffffff', fontSize: 34, fontWeight: 'bold', }, }); AppRegistry.registerComponent('Slideshow', () => Slideshow);
Now after saving and reloading app you should see the following, and it’s all done!
If you are stuck and need help, you can refer to the completed solution.