最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - How to use three.js with React - Stack Overflow

matteradmin4PV0评论

I am trying to use three.js in a React application however even the basic sample from the three.js docs fails to load on the canvas.

I first made a vanilla.js sandbox implementation with the sample which works fine. Then I ported it over to create a react+three.js minimal sandbox implementation which fails to work.

Can anyone have a look at it and point me in the right direction ?

class Viewer extends Component {
    state = {};

    scene = null;

    camera = null;

    renderer = new WebGLRenderer();

    inst = 0;

    viewerRef = React.createRef();

    ponentDidMount() {
        const { domElement } = this.renderer;
        this.scene = new Scene();
        this.scene.background = new Color("#ccc");
        this.camera = new Camera(
        75,
        domElement.innerWidth / domElement.innerHeight,
        0.1,
        1000
        );
        this.renderer.setSize(domElement.innerWidth, domElement.innerHeight);
        this.viewerRef.current.appendChild(this.renderer.domElement);
        const geometry = new BoxGeometry(1, 1, 1);
        const material = new MeshBasicMaterial({ color: 0x05ff00 });
        const cube = new Mesh(geometry, material);

        this.scene.add(cube);

        this.camera.position.z = 5;
        this.display();
    }

    display = () => {
        this.renderer.render(this.scene, this.camera);
        requestAnimationFrame(this.display);
    };

    render = () => <div className="viewer" ref={this.viewerRef} />;
}

I am trying to use three.js in a React application however even the basic sample from the three.js docs fails to load on the canvas.

I first made a vanilla.js sandbox implementation with the sample which works fine. Then I ported it over to create a react+three.js minimal sandbox implementation which fails to work.

Can anyone have a look at it and point me in the right direction ?

class Viewer extends Component {
    state = {};

    scene = null;

    camera = null;

    renderer = new WebGLRenderer();

    inst = 0;

    viewerRef = React.createRef();

    ponentDidMount() {
        const { domElement } = this.renderer;
        this.scene = new Scene();
        this.scene.background = new Color("#ccc");
        this.camera = new Camera(
        75,
        domElement.innerWidth / domElement.innerHeight,
        0.1,
        1000
        );
        this.renderer.setSize(domElement.innerWidth, domElement.innerHeight);
        this.viewerRef.current.appendChild(this.renderer.domElement);
        const geometry = new BoxGeometry(1, 1, 1);
        const material = new MeshBasicMaterial({ color: 0x05ff00 });
        const cube = new Mesh(geometry, material);

        this.scene.add(cube);

        this.camera.position.z = 5;
        this.display();
    }

    display = () => {
        this.renderer.render(this.scene, this.camera);
        requestAnimationFrame(this.display);
    };

    render = () => <div className="viewer" ref={this.viewerRef} />;
}
Share Improve this question asked Dec 30, 2018 at 16:57 jagzviruzjagzviruz 1,51313 silver badges28 bronze badges 2
  • HERE is a three.js / react thing I did a while ago, maybe taking a look at it, specifically the Scene ponent will help you. – 2pha Commented Dec 31, 2018 at 1:22
  • thank you all for taking the time to answer. I had abandoned my efforts, and have to revisit if this solved my issues. will soon respond. – jagzviruz Commented Apr 23, 2019 at 9:21
Add a ment  | 

3 Answers 3

Reset to default 2

Here is CodeSandBox that works with a basic React wrapper code for Three.js. It also has THREE.OrbitControls integration and scale on resize code:

https://codesandbox.io/s/github/supromikali/react-three-demo

Live demo: https://31yp61zxq6.codesandbox.io/

Here is a full code snippet in the case above listed links don't work for you:

index.js code

import React, { Component } from "react";
import ReactDOM from "react-dom";
import THREE from "./three";


class App extends Component {
    ponentDidMount() {


        // BASIC THREE.JS THINGS: SCENE, CAMERA, RENDERER
        // Three.js Creating a scene tutorial
        // https://threejs/docs/index.html#manual/en/introduction/Creating-a-scene
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(
            75,
            window.innerWidth / window.innerHeight,
            0.1,
            1000
        );
        camera.position.z = 5;

        var renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);



        // MOUNT INSIDE OF REACT
        this.mount.appendChild(renderer.domElement); // mount a scene inside of React using a ref



        // CAMERA CONTROLS
        // https://threejs/docs/index.html#examples/controls/OrbitControls
        this.controls = new THREE.OrbitControls(camera);



        // ADD CUBE AND LIGHTS
        // https://threejs/docs/index.html#api/en/geometries/BoxGeometry
        // https://threejs/docs/scenes/geometry-browser.html#BoxGeometry
        var geometry = new THREE.BoxGeometry(2, 2, 2);
        var material = new THREE.MeshPhongMaterial( {
            color: 0x156289,
            emissive: 0x072534,
            side: THREE.DoubleSide,
            flatShading: true
        } );
        var cube = new THREE.Mesh(geometry, material);
        scene.add(cube);

        var lights = [];
        lights[ 0 ] = new THREE.PointLight( 0xffffff, 1, 0 );
        lights[ 1 ] = new THREE.PointLight( 0xffffff, 1, 0 );
        lights[ 2 ] = new THREE.PointLight( 0xffffff, 1, 0 );

        lights[ 0 ].position.set( 0, 200, 0 );
        lights[ 1 ].position.set( 100, 200, 100 );
        lights[ 2 ].position.set( - 100, - 200, - 100 );

        scene.add( lights[ 0 ] );
        scene.add( lights[ 1 ] );
        scene.add( lights[ 2 ] );



        // SCALE ON RESIZE

        // Check "How can scene scale be preserved on resize?" section of Three.js FAQ
        // https://threejs/docs/index.html#manual/en/introduction/FAQ

        // code below is taken from Three.js fiddle
        // http://jsfiddle/Q4Jpu/

        // remember these initial values
        var tanFOV = Math.tan( ( ( Math.PI / 180 ) * camera.fov / 2 ) );
        var windowHeight = window.innerHeight;

        window.addEventListener( 'resize', onWindowResize, false );

        function onWindowResize( event ) {

            camera.aspect = window.innerWidth / window.innerHeight;

            // adjust the FOV
            camera.fov = ( 360 / Math.PI ) * Math.atan( tanFOV * ( window.innerHeight / windowHeight ) );

            camera.updateProjectionMatrix();
            camera.lookAt( scene.position );

            renderer.setSize( window.innerWidth, window.innerHeight );
            renderer.render( scene, camera );

        }



        // ANIMATE THE SCENE
        var animate = function() {
            requestAnimationFrame(animate);

            cube.rotation.x += 0.01;
            cube.rotation.y += 0.01;

            renderer.render(scene, camera);
        };

        animate();
    }
    render() {
        return <div ref={ref => (this.mount = ref)} />;
    }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

three.js code (THREE.OrbitControls import)

import * as THREE from 'three';


window.THREE = THREE; // THREE.OrbitControls expects THREE to be a global object
require('three/examples/js/controls/OrbitControls');


export default {...THREE, OrbitControls: window.THREE.OrbitControls};

Result should look like this:

I am not sure why nobody has mentioned react-three-fiber. It's a React renderer for ThreeJS.

Best part is, using rollupjs, we can even tree-shake a lot of unnecessary code, that we won't use in our React ThreeJS app. Also, using react-three-fiber in a desired way, we can achieve 60FPS for our ThreeJS animations

Post a comment

comment list (0)

  1. No comments so far