The demonstration application can be viewed live here — a mobile phone or WebVR-compatible browser is required to switch from 3d-mode to full stereoscopic VR-mode. The source code for the application is available on Github.

Let’s get technical

The application is fully built with React, Redux and Webpack — libraries that will be familiar to most front end developers. The aframe-react library acts as a bridge between A-Frame and React, and the react-redux library helps us connect our components cleanly with our state.

The state consists of two entries:

A boolean vrMode that indicates if components should render their 3d/VR representation using A-Frame, or their 2d representation using regular html and css.

An array of members with their id, name, photo and type.

When a member is clicked in either mode, the NEXT_MEMBER_TYPE Redux action is dispatched, the member type is changed and React takes care of re-rendering as needed. Because A-Frame is just markup and components from aframe-react are used, this re-rendering works seamlessly in both 2d and 3d mode.

When the button to enable 3d mode is clicked, the ENABLE_VR_MODE Redux action is dispatched. This simply changes the vrMode boolean in the state to true, and again Redux and React handles applying and rendering the new state.

In a large-scale application, it might be better to split components into “2d” and “3d” components and have containers choose the right one depending on the state, but in this example I have opted to have both renderings in the same component. The Wrapper container, as illustrated above, simply renders A-Frame markup when vrMode is enabled and regular html when it is not.

The Members container needs to only make one difference depending on the mode of rendering: React requires render methods to always return one node, and while this container node can be a regular div in 2d mode, it must be an A-Frame Entity element in 3d mode. The Entity element is the basic building block of A-Frame, but it is also A-Frame’s equivalent of a “neutral” container such as the div element. If a div is used as a container in 3d mode, nothing will be rendered in the canvas as the scene contains invalid markup.

The Member component (not to be confused with the plural Members container, sorry for the confusing naming), also looks at vrMode to determine how to render itself. In 3d mode, the Entity component provided by aframe-react is used to render a box with the profile photo as a texture tinted with the color derived from the member type. In 2d mode, a regular div with an image inside is rendered, and a state-modifying class is added depending on the member’s type.

In both cases, it is possible to use the same onClick callback when the member is clicked, whether that’s coming from clicking a div element on a web page or box in virtual reality. Redux handles the action and updates the state, and React re-renders as needed. In this setup, the libraries don’t need to know anything about how the state is rendered to do their thing.

Again, to review the source code in its entirety and play with it locally, head over to the repository on Github.

In conclusion

With A-Frame, web developers can easily get started on building 3d and VR visualizations, and they can apply these visualizations to existing React-based applications with a minimum of changes. This is especially true if the architecture uses the principles of Flux, as the shared unidirectional state and event flow lends itself well to many different representations of the same data.

I encourage everyone who are building VR business software to consider if a combination between 2d and 3d/VR might be the best approach, and if such a user experience wouldn’t make most sense in the browser. On top of that, it could also be faster to implement this way, depending on your team’s skill set.

Adding that “VR feature” to your existing web-based SaaS solution could be a low-hanging fruit with this approach. Wouldn’t your users prefer virtual reality visualizations directly in their browser as opposed to downloading yet another mobile app or — gasp — installing actual desktop software? Wouldn’t you?