How do I keep some element fixed on the screen in react-VR

南楼画角 提交于 2019-12-05 18:22:30

The answer is to use multiple surfaces: one that isn't headlocked and another that is headlocked.

See "Using Multiple Surfaces" here: Surfaces - React 360

To get yours working, paste the missing code from the example into your client.js and index.js files respectively:

Here is a link to a working example (partially pasted below): Headlocked Surfaces

import { Math as VRMath, ReactInstance, Surface } from "react-360-web";

function init(bundle, parent, options = {}) {
  const horizontalPanel = new Surface(300, 300, Surface.SurfaceShape.Flat);
  const hvPanel = new Surface(300, 300, Surface.SurfaceShape.Flat);

  horizontalPanel.setAngle(0, -0.5);

  const cameraDirection = [0, 0, -1];

  const r360 = new ReactInstance(bundle, parent, {
    fullScreen: true,
    frame: () => {
      const cameraQuat = r360.getCameraQuaternion();
      cameraDirection[0] = 0;
      cameraDirection[1] = 0;
      cameraDirection[2] = -1;
      // cameraDirection will point out from the view of the camera,
      // we can use it to compute surface angles
      VRMath.rotateByQuaternion(cameraDirection, cameraQuat);
      const cx = cameraDirection[0];
      const cy = cameraDirection[1];
      const cz = cameraDirection[2];
      const horizAngle = Math.atan2(cx, -cz);
      const vertAngle = Math.asin(cy / Math.sqrt(cx * cx + cy * cy + cz * cz));
      horizontalPanel.setAngle(horizAngle, -0.5);
      hvPanel.setAngle(horizAngle, vertAngle);
    },
    ...options
  });

  r360.renderToSurface(r360.createRoot("HorizontalPanel"), horizontalPanel);
  r360.renderToSurface(r360.createRoot("HVPanel"), hvPanel);
}

window.React360 = { init };

In your client.js:

Inside the frame property of the ReactInstance constructor, set the surface angle to match the camera: either horizontally, or both horizontally and vertically.

In your index.js:

Remember to register a React component to the new headlocked surface.

Updated gist which has less delay as it's subscribed to the HM:

https://gist.github.com/cidicles/b4e978d3f3e2de8b359bdc51b5fb3261


This is how I am currently doing this. It has visual lag and sets state in a loop but achieves the goal.

Create a state for the VrheadModel.rotation() array

constructor(props) {
  super(props);
  this.state = {
    hmRot: VrHeadModel.rotation()
  }
}

Start a timer

componentDidMount(){
  this.timer = setInterval(()=>{this.tick()}, 50);
}
componentWillUnmount(){
  clearInterval(this.timer);
}
tick(){
  this.setState({
    hmRot: VrHeadModel.rotation()
  });
}

Create a view at 0/0/0 and position your fixed object in the scene as you normally world. Set the rotation on the master view to match the rotation of the camera.

  render(){
    let {hmRot} = this.state;
    return (
      <View
        style={{
          position: 'absolute',
          layoutOrigin: [0.5, 0.5],
          transform: [
            {translate: [0, 0, 0]},
            {rotateX: hmRot[0]},
            {rotateY: hmRot[1]},
            {rotateZ: hmRot[2]}
          ]
        }}>
        <Text
          style={{
            position: 'absolute',
            layoutOrigin: [0.5, 0.5],
            backgroundColor: '#f00',
            transform: [
              {translate: [0, 0, -2]},
            ]
          }}>
          Fixed
        </Text>
      </View>
    );
  }

There is a relevant post around this issue from the React VR team here: https://github.com/facebook/react-vr/issues/261

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!