facebookarchive / react-360

Create amazing 360 and VR content using React
https://facebook.github.io/react-360
Other
8.73k stars 1.23k forks source link

How could I make gaze buttons using React VR? #168

Closed HeinPauwelyn closed 7 years ago

HeinPauwelyn commented 7 years ago

I'm creating an VR application using React VR and would make gaze buttons with a progress bar (or something) to show the user how long he must watch to that button. How could I do that?

I'm thinking to use this pseudocode (my be some bug inside this code):

constructor(props) {
    super(props);
    this.state = {
        watchTime: 3,
        progress: 0,
        watching: true
    };
}

render() {
    return (
        <VrButton onEnter={ () => this.animateProgress() }
                  onExit={ () => this.stopProgress() }
                  onClick={ ()=> this.click() }></VrButton>
    );
}

animateProgress() {
    this.setState({watching: true});
    while (this.state.watchTime >== this.state.progress && this.state.watching === true) {
        // after a timeout of one second add 1 to `this.state.progress`
    }

    this.click();
}

stopProgress() {
    this.setState({
        progress: 0,
        watching: false
    });
}

click() {
    // Handels the click event
}

Is there an easier way to do this?


See also this question on Stack Overflow bounty of 50 reputation points!

HeinPauwelyn commented 7 years ago

Please anwser this question. My reputation on school depend on it! I've ask it on the Reactiflux Chat channel, the Github repository of React VR and on Stack Overflow with an open bounty of 50 reputation, but no where I got an answer or even a comment that could help me.

andrewimm commented 7 years ago

The while() loop in your code is going to lock up your entire application. Instead, you want something along the lines of this:

constructor(props) {
    super(props);
    this.click = this.click.bind(this); // make sure this.click is in the right context when the timeout is called
}

render() {
    return (
        <VrButton onEnter={ () => this.animateProgress() }
                  onExit={ () => this.stopProgress() }
                  onClick={ ()=> this.click() }></VrButton>
    );
}

animateProgress() {
    this.timeout = this.setTimeout(this.click, 1000); // or however many milliseconds you want to wait
    // begin animation
}

stopProgress() {
    clearTimeout(this.timeout);
    this.timeout = null;
    // end animation
}

click() {
  // ...
}

Setting the timeout ensures that unless it is cancelled (during the onExit event), we will trigger the click method in 1000 ms, without blocking any other JS execution.

I'll try to put out a blog post this weekend to describe gaze buttons in more depth.

HeinPauwelyn commented 7 years ago

Thanks for your answer. It helps me a lot.

P.S.: Could you answer also my question on Stack Overflow so I could give you my bounty?

Shelvadim commented 6 years ago

Hi, I found that this code does not work anymore, it shows error:

executeDispatchesAndReleaseTopLevel@file:///G:\ReactVR\island\node_modules\react-native\Libraries\Renderer\ReactNativeStack-dev.js 276:11 executeDispatchesAndRelease@file:///G:\ReactVR\island\node_modules\react-native\Libraries\Renderer\ReactNativeStack-dev.js 272:33 Object.executeDispatchesInOrder@file:///G:\ReactVR\island\node_modules\react-native\Libraries\Renderer\ReactNativeStack-dev.js 208:263 executeDispatch@file:///G:\ReactVR\island\node_modules\react-native\Libraries\Renderer\ReactNativeStack-dev.js 202:88 Object.invokeGuardedCallbackAndCatchFirstError@file:///G:\ReactVR\island\node_modules\react-native\Libraries\Renderer\ReactNativeStack-dev.js 169:58 Object.invokeGuardedCallback@file:///G:\ReactVR\island\node_modules\react-native\Libraries\Renderer\ReactNativeStack-dev.js 166:37 Object.invokeGuardedCallback@file:///G:\ReactVR\island\node_modules\react-native\Libraries\Renderer\ReactNativeStack-dev.js 130:13 Object._onEnter@file:///G:\ReactVR\island\node_modules\react-vr\Libraries\VrButton\VrButton.js 339:37 Object.onEnter@file:///G:\ReactVR\island\index.vr.js 168:41 island.animateProgress@file:///G:\ReactVR\island\index.vr.js 38:26

this.setTimeout is not a function


This code is working now:

constructor(props) { super(props); this.click = this.click.bind(this); // make sure this.click is in the right context when the timeout is called }

render() { return ( <VrButton onEnter={ () => this.animateProgress() } onExit={ () => this.stopProgress() } onClick={ ()=> this.click() }> ); } animateProgress() {
this.timeout = setTimeout(()=> { this.setState(this.click) }, 3000) // or however many milliseconds you want to wait // begin animation console.log('ok'); }

stopProgress() { clearTimeout(this.timeout); this.timeout = null; console.log('stop'); // end animation }

click() { console.log('click'); }