I understand how vrButtons work, but how would someone go about creating buttons that are overlayed onto the vr hud. Buttons that are static, and stay on the screen regardless of how the camera is oriented.
3 Answers
I had the same problem and I used DOM Overlay. I found a solution with the help of the https://github.com/facebook/react-vr/tree/master/Examples/DomOverlaySample example and a Website made by Facebook here: https://apps-1523878944298007.apps.fbsbx.com/instant-bundle/1523857704355225/1209114435855717/index.html
Update: I added a solution with a Callback to the index.vr.js with the help of this: https://github.com/facebook/react-vr/issues/418
First edit the cient.js
:
import '../process'; //important to avoid a error for DOM
import {VRInstance} from 'react-vr-web';
import DashboardModule from "../DashboardModule";
// Create a div where the overlay will be displayed in the DOM.
const domDashboardContainer = document.createElement('div');
domDashboardContainer.id = 'persistent-overlay';
// Create an instance of the module, to be registered below.
const domDashboardModule = new DashboardModule(domDashboardContainer);
function init(bundle, parent, options) {
const vr = new VRInstance(bundle, 'SuMDemo', parent, {
// Show a gaze cursor.
cursorVisibility: 'visible',
...options,
// Register dom overlay module upon initialization.
nativeModules: [domDashboardModule],
});
// Inject DOM overlay container to the player so that it is rendered properly.
vr.player._wrapper.appendChild(domDashboardContainer);
// Attach the React Native Context to the Model
domDashboardContainer._setRNContext(vr.rootView.context);
vr.render = function() {
//executing on every render of the vr app
};
// Begin the animation loop
vr.start();
return vr;
}
window.ReactVR = {init};
Don't forget to import the process.js
(can be found here https://github.com/facebook/react-vr/blob/master/Examples/DomOverlaySample/process.js). It's a workaround to avoid an error.
The DashboardModule.js
renders the react elements of the DOM Overlay. Here is an example:
import React from 'react';
import ReactDOM from 'react-dom';
import {Module} from 'react-vr-web';
import Dashboard from './DashboardLayout';
export default class DashboardModule extends Module {
constructor(overlayContainer) {
super('DashboardModule'); //Name for the call in index.vr.js
this._overlayContainer = overlayContainer;
this._rnctx = null; //react native context for callback
}
// This method call opens up the overlay for display.
showDashboard(props, callBackBtn) {
this.callBackBtn=callBackBtn;
ReactDOM.render(
<Dashboard
{...props}
onClickDash={()=>this.buttonClicked()}
/>,
this._overlayContainer
);
}
//setter for context
_setRNContext(rnctx) {
this._rnctx = rnctx;
}
buttonClicked() {
console.log("Dashboard Button Clicked");
//here invoke the Callback.In the second parameter ([]) you can pass arguments
this._rnctx.invokeCallback(this.callBackBtn, []);
}
hideDashboard() {
ReactDOM.unmountComponentAtNode(this._overlayContainer);
}
}
And the DashboardLayout.js
can look like this:
import React from 'react';
const Dashboard = props => {
return (
<div style={{
bottom: 0,
left: 0,
position: 'absolute',
right: 0,
top: 0,
pointerEvents: 'none', //important that the movement is possible
}}>
<div style={{
background: 'rgba(0, 0, 0, 0.7)',
border: '2px solid #ffffff',
borderRadius: '5px',
top: '20px',
display: 'inline-block',
height: '40px',
width: '40px',
marginLeft: 'auto',
padding: '4px',
position: 'absolute',
right: '18px',
verticalAlign: 'top',
opacity: '1',
cursor: 'pointer',
pointerEvents: 'auto',
}}
onClick={props.onClickDash}>
<div style={{
margin: '4px',
width: '32px',
height: '32px',
backgroundImage: 'url(../static_assets/icons/menu.png)',
}}>
</div>
</div>
</div>
);
};
export default Dashboard;
It's important to set pointerEvents
to none
in the outer and set it again to auto
in the where the button is placed. Otherwise the VR movement is not working any more with a mouse.
You can call Methods from the DashboardModule.js
via NativeModules (import them from react-vr) in the index.vr.js
.
To show the DOM Overlay call in the index.vr.js
:
NativeModules.DashboardModule.showDashboard(
{
someProps: 1 //here pass some props
},
()=>this.callBackBtn() //this is the callback function that should be called
);
The name of the NativeModule is set in the constructor of the DashboardModule.js
, in this case DashboardModule
.

- 31
- 4
-
This is great, thanks. How do you pass the buttonClicked event back to index.vr.js? – cal Dec 13 '17 at 10:44
-
That is a problem I haven't found a solution yet. – luki Dec 13 '17 at 14:01
-
Strangely from DashboardModule I can access props from index.vr.js but I can't call functions – cal Dec 13 '17 at 14:41
You will find some challenges here if you decide to use a gaze cursor in VR for these buttons but you have two options.
You can create a fixed component. You can check out my gist for one of these using the VRHeadModel here: https://gist.github.com/cidicles/b4e978d3f3e2de8b359bdc51b5fb3261
You can use this just like:
<Fixed>Something You Want Fixed</Fixed>
This approach is a VR solution and this element will be present in the VR scene but it does have a little bit of lag between updates.
The other method is to use a DOM Overlay. You can check out this example here: https://github.com/facebook/react-vr/tree/master/Examples/DomOverlaySample
This is just traditional DOM so there is no lag just keep in mind any elements here will not be visible while in VR.

- 351
- 2
- 8
I want to step back a moment and think about this.
The main question would be, is this for VR view or are you just using a 3D view on a web-page without intending people to go into VR?
When you create something that, in VR, "always stays stationary" what you are doing is creating a floating object that the user can't shake off. It'll feel very, very strange in VR.
Worse, as they move their head around, the floating object will seem to penetrate other objects, depending on your precise headset and the optics. It'll be at a neutral distance (focal plane) and cause some focusing problems as well. This might trigger the vergence-accomodation sickness issue. (This is actually more of a fatigue issue than sickness, but YSMV - your stomach may vary).
It really is best to make a 3D UI when you are in a 3D world. It's hard, it really is - this is a field that entire PhD's have been granted in over the years. (VR is not, despite popular conception, new).
Sorry for the "non-answer answer" ... I hope this helps a little bit.

- 931
- 10
- 15