Bring Virtual Reality to Your Browser with React VR

Illustration by Tomasz Cichos

One of the latest technologies that will change interactions between humans and computers is definitely Virtual Reality. It’s not a new medium, but due to rapid technology progress, VR’s popularity is thriving like never before. Alongside with Augmented Reality, VR seems to be the next computing platform. Now, thanks to browser vendors’ effort, this technology is at our fingertips.

WebVR, recently renamed to WebXR (see why here), enables building VR experiences using the browser’s environment. This allows us to make VR applications that can run on various devices. Aside great reachability, making VR in Web can greatly increase it’s popularity in the next few years.

How to use WebVR

VR in web browsers is available to use by WebVR API (see docs). This API enables VR display mode, helps with handling the Head-Mounted Display (HMD) orientation and adds controllers / gamepads support (used alongside with Gamepad API).

The WebVR API is available mostly in window and navigator objects, directly in the browser context. Unfortunately, WebVR is not yet a Living Standard, so in order to use it, you need to enable it in your browser’s settings. In Chrome you can do it by going to chrome://flags and turning on theWebVR flag. Also support of this API is not that wide (see the table here). I suggest using a polyfill provided by Google for browsers that don’t support WebVR.

To build 3D scene that you will present in VR mode, you still need a WebGL engine. Luckily, there are plenty of libraries which can help you with 3D in browser. One of the most popular one is three.js which I highly recommend to use.

When you build your 3D scene using WebGL, you can display it in VR mode using the WebVR API. To do this, you need to get all available VR displays using getVRDisplays() method. It returns a Promise with all displays that support VR. After you grab your display, you have to call requestPresent() on your display instance. VR display has it’s own requestAnimationFrame() method to sync your scene frame rate for better performance. See a simple example below:

What is ReactVR

In simple terms, ReactVR is a combination of React framework and WebVR API. You get WebVR supported by React’s declarative component API, which makes 3D objects manipulation pretty straightforward. Every object on the scene is represented by React’s component, so any property change updates it instantly. It greatly simplifies work with 3D environment in the browser.

Under the hood, ReactVR is a mix of React, React Native and three.js libraries (see figure below).

Thanks to thread separation, operations performed on React components don’t affect Main Thread, so 3D rendering process is not interrupted by Virtual DOM modifications. It’s worth to keep that in mind, especially when you would like to add any custom modules. Due to part of the application doesn’t work in browser’s context, you need to use special events to communicate between React and ReactVR. It’s natural behaviour for Web Workers, so if you need more details about this API, I encourage you to take a look at the docs.

Beside React’s Virtual DOM and threads separation, ReactVR provides a set of tools and utilities, which makes your work easier. You have an access to animations library, current gamepads / controllers and even to sound effects. This framework has everything you need to build robust and interactive VR applications.

Building basic VR scene

Now, you have a brief overview how ReactVR looks and works. Before we start building our first scene, I suggest you to install ReactVR CLI and create a project with it. All required informations how to do it, you can find in the Getting Started docs.

Let’s build a basic 3D scene using it’s builtin components. First of all, we will need a container for all 3D objects on the scene. ReactVR has two components that fit for the job. The View component, which is also a most generic ReactVR component, and the Scene component. The latter one, also allows you to move camera on the scene.

Most of the virtual tours are based on 360° panoramic photos. ReactVR has dedicated component for embedding such photos, it’s called Pano. Lastly, ReactVR supports adding text to your scene. With Text component you can define your own text, which will appear as 3D text object on scene.

Here’s the code:

And here’s the result:

Moving things on your scene

As you see, building basic panorama based scene is pretty easy in ReactVR. But what if you want to move object’s on the scene, to introduce some interaction? You can add any animation library, like GSAP or anime.js. In my opinion it’s better to use a integrated one.

ReactVR ships with Animated utility (based on React Native’s Animated class), which helps in adding motion to your VR experience. To use it, you need to import Animated class directly from react-vr module and declare animated properties in component’s state, as follows:

The above example, shows how to add animate Text element’s rotation, after it’s mounted on the scene. ReactVR supports also various input listeners, which helps with reacting to user’s actions. Two useful listeners are onEnter and onExit. The first one calls event listener, when the cursor is on. The latter, when cursor if off the target element. Let’s improve example, using these listeners:

See the result:

Customising ReactVR

ReactVR provides a wide set of predefined components that are useful for building a basic 3D scene, but you can make your own ones. You can do it in two ways. The easiest one is to compose builtin components in custom component, but it can be not flexible enough. You can’t access three.js context in predefined components. In order to use it’s API you need to make a Native Module or custom View.

Native Modules allows to use your custom classes and functions within ReactVR context. It acts as a bridge between UI and Web Worker thread. In components you don’t have an access to DOM. With custom Native Module, it is possible to use any DOM-dependent API with ReactVR. For example, you can check if user is online, listening to online and offline events (see docs) and update scene accordingly to it’s state. Check out ReactVR’s documentation for more informations.

If you need to go deeper into ReactVR, custom View is a must. Thus, building your own View is more complicated than using Native Modules, you get low-level access. It’s worth to mention that all builtin components like Box or Pano are Views. Since in ReactVR there is no TorusKnot component, let’s make one using custom View:

Here’s a TorusKnot custom View class:

Next step is to create React TorusKnot class, set allowed properties and make it a native component:

Lastly, we need to register TorusKnot as custom View in client.js file:

And there’s the result:

Building the project

When your project is finished, it’s time to build a production version of our VR experience. ReactVR provides you tools for building project bundle. Although ReactVR is built upon React Native, is not yet possible to build your project as native mobile application (see why here). Still you can make a web application bundle and embed it into WebView.

Bundling ReactVR is pretty simple, just run npm run bundle. This will create build directory in vr folder with compiled version of your application. Then you can push production bundle to your favourite static file server like Heroku or Amazon AWS S3. I suggest you to take a look at official docs to get more informations.

Further reading

WebVR is a very fascinating technology. It allows us build Virtual Reality experience directly in our browsers. ReactVR seems to be a right extension of this API. Both WebVR and ReactVR are brand new technologies, so if you seek more informations about them, I suggest you to read these articles and docs:

You liked it? Tap the 👏 button! Thank you!

You can find me on Twitter and Github.