How to connect Threejs to React?

后端 未结 5 1040
[愿得一人]
[愿得一人] 2020-12-07 16:39

I work with React and use a canvas. I want to change the canvas to WebGL (Threejs library). How to connect this library to React?

I have some element, e.g.

相关标签:
5条回答
  • 2020-12-07 17:17

    I have converted the first example of three.js to React thing. Hope this is helpful import React from 'react'; import './App.css'; import * as THREE from 'three';

    class App extends React.Component{
      constructor(props){
        super(props)
        this.scene = new THREE.Scene();
        this.camera = new THREE.PerspectiveCamera(75,
          window.innerWidth / window.innerHeight,
          0.1,
          1000
          );
        this.renderer = new THREE.WebGL1Renderer();
            this.renderer.setSize( window.innerWidth, window.innerHeight );
        this.geometry = new THREE.BoxGeometry();
        this.material = new THREE.MeshBasicMaterial( { color: 0x32a852});
            this.cube = new THREE.Mesh( this.geometry, this.material)
      }
      animate = () => {
        requestAnimationFrame(this.animate)
        this.cube.rotation.x += 0.01;
        this.cube.rotation.y += 0.01;
        this.renderer.render(this.scene, this.camera);
        
      }
      componentDidMount() {
            document.body.appendChild( this.renderer.domElement );
            this.scene.add( this.cube );
            this.camera.position.z = 5;
            this.animate()
        }
      render(){
        return(
          <body id='document-body-01'>
          </body>
        );
      }
    }
    
    export default App;
    

    So the idea is that the three components can be broken down to constructor, function of animate and componentdidmount. I believe this.varname can be place anywhere. I felt constructor was a good place. This way other examples can be set as well.

    0 讨论(0)
  • 2020-12-07 17:23

    You can using library https://github.com/toxicFork/react-three-renderer

    Installation

    npm install --save react@15.5.3 react-dom@15.5.3 three@0.84.0
    npm install --save react-three-renderer
    

    Usage

    import React from 'react';
    import React3 from 'react-three-renderer';
    import * as THREE from 'three';
    import ReactDOM from 'react-dom';
    
    class Simple extends React.Component {
      constructor(props, context) {
        super(props, context);
    
        // construct the position vector here, because if we use 'new' within render,
        // React will think that things have changed when they have not.
        this.cameraPosition = new THREE.Vector3(0, 0, 5);
    
        this.state = {
          cubeRotation: new THREE.Euler(),
        };
    
        this._onAnimate = () => {
          // we will get this callback every frame
    
          // pretend cubeRotation is immutable.
          // this helps with updates and pure rendering.
          // React will be sure that the rotation has now updated.
          this.setState({
            cubeRotation: new THREE.Euler(
              this.state.cubeRotation.x + 0.1,
              this.state.cubeRotation.y + 0.1,
              0
            ),
          });
        };
      }
    
      render() {
        const width = window.innerWidth; // canvas width
        const height = window.innerHeight; // canvas height
        return (<React3
          mainCamera="camera" // this points to the perspectiveCamera which has the name set to "camera" below
          width={width}
          height={height}
    
          onAnimate={this._onAnimate}
        >
          <scene>
            <perspectiveCamera
              name="camera"
              fov={75}
              aspect={width / height}
              near={0.1}
              far={1000}
              position={this.cameraPosition}
            />
            <mesh
              rotation={this.state.cubeRotation}
            >
              <boxGeometry
                width={1}
                height={1}
                depth={1}
              />
              <meshBasicMaterial
                color={0x00ff00}
              />
            </mesh>
          </scene>
        </React3>);
      }
    }
    ReactDOM.render(<Simple/>, document.body);
    
    0 讨论(0)
  • 2020-12-07 17:35

    Here is an example of how to set this up (see demo):

    import React, { Component } from 'react'
    import * as THREE from 'three'
    
    class Scene extends Component {
      constructor(props) {
        super(props)
    
        this.start = this.start.bind(this)
        this.stop = this.stop.bind(this)
        this.animate = this.animate.bind(this)
      }
    
      componentDidMount() {
        const width = this.mount.clientWidth
        const height = this.mount.clientHeight
    
        const scene = new THREE.Scene()
        const camera = new THREE.PerspectiveCamera(
          75,
          width / height,
          0.1,
          1000
        )
        const renderer = new THREE.WebGLRenderer({ antialias: true })
        const geometry = new THREE.BoxGeometry(1, 1, 1)
        const material = new THREE.MeshBasicMaterial({ color: '#433F81' })
        const cube = new THREE.Mesh(geometry, material)
    
        camera.position.z = 4
        scene.add(cube)
        renderer.setClearColor('#000000')
        renderer.setSize(width, height)
    
        this.scene = scene
        this.camera = camera
        this.renderer = renderer
        this.material = material
        this.cube = cube
    
        this.mount.appendChild(this.renderer.domElement)
        this.start()
      }
    
      componentWillUnmount() {
        this.stop()
        this.mount.removeChild(this.renderer.domElement)
      }
    
      start() {
        if (!this.frameId) {
          this.frameId = requestAnimationFrame(this.animate)
        }
      }
    
      stop() {
        cancelAnimationFrame(this.frameId)
      }
    
      animate() {
        this.cube.rotation.x += 0.01
        this.cube.rotation.y += 0.01
    
        this.renderScene()
        this.frameId = window.requestAnimationFrame(this.animate)
      }
    
      renderScene() {
        this.renderer.render(this.scene, this.camera)
      }
    
      render() {
        return (
          <div
            style={{ width: '400px', height: '400px' }}
            ref={(mount) => { this.mount = mount }}
          />
        )
      }
    }
    
    export default Scene
    

    You might also be interested in a full screen example (see GitHub).

    Here's an example using React Hooks instead of a class.

    0 讨论(0)
  • 2020-12-07 17:42

    I know question is a tad old, but if somebody's still looking for something. You'd try https://github.com/drcmda/react-three-fiber. They've some snippet and demos on their github.

    0 讨论(0)
  • 2020-12-07 17:44

    If you are working with hooks. here is an example of a loaded 3D model from three.js with React.js.

    https://github.com/sarat9/react-threejs-sample/blob/master/src/animations/SoldierMachineAnimation/index.jsx

    0 讨论(0)
提交回复
热议问题