React x Three.js: resizing is not working

Hello everyone!

I’m using React, making a three.js shape in a component.

I am using the function updateDimensions() on window resize but the resizing is not working. I’m guessing that this has to do with hardcoding the canvas’ size in the render function, i’ve tried alternatives but it didn’t work if don’t specify the dimensions in render.

any help would be appreciated :slight_smile: thank you!

here is my code:

class Shape extends Component {
    constructor(props) {
        super(props);
        this.animate = this.animate.bind(this);

        this.updateDimensions = this.updateDimensions.bind(this);
    }
    componentDidMount() {
        const width = this.mount.clientWidth;
        const height = this.mount.clientHeight;

        window.addEventListener("resize", this.updateDimensions);

        // scene
        this.scene = new THREE.Scene();

        // camera
        this.camera = new THREE.PerspectiveCamera(
            75,
            window.innerWidth / window.innerHeight,
            0.1,
            50
        );
        this.camera.position.z = 30;

        // rendering
        this.renderer = new THREE.WebGLRenderer({
            antialias: true,
            alpha: true
        });
        this.renderer.setClearColor(0x000000, 0);
        this.renderer.setSize(width, height, false);
        this.camera.aspect = width / height;
        this.camera.updateProjectionMatrix();

        this.renderer.render(this.scene, this.camera);
        this.mount.appendChild(this.renderer.domElement);

        // sphere
        const particleMat = new THREE.PointsMaterial({
            color: 0xaecdd0,
            size: 0.1,
            map: new THREE.TextureLoader().load("/particle.jpg"),
            transparent: true,
            blending: THREE.AdditiveBlending,
            depthWrite: false
        });

        const particleGeo = new THREE.SphereGeometry(15, 300, 300);

        particleGeo.vertices.forEach(function(vertex) {
            vertex.x += Math.random() - 0.2;
            vertex.y += Math.random() - 0.2;
            vertex.z += Math.random() - 0.2;
        });

        const particleSystem = new THREE.Points(particleGeo, particleMat);
        particleSystem.name = "particleSystem";

        this.scene.add(particleSystem);

        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);

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

        this.renderer.render(this.scene, this.camera);

        this.animate();
    }

    componentWillUnmount() {
        window.removeEventListener("resize", this.updateDimensions);
        this.mount.removeChild(this.renderer.domElement);
    }

    animate() {
        requestAnimationFrame(this.animate);
        const particleSystem = this.scene.getObjectByName("particleSystem");
        particleSystem.rotation.y += 0.005;
        this.renderer.render(this.scene, this.camera);
    }

    updateDimensions() {
        if (this.mount !== null) {
            this.renderer.setSize(
                this.mount.clientWidth,
                this.mount.clientHeight
            );
            this.camera.aspect =
                this.mount.clientWidth / this.mount.clientHeight;
            this.camera.updateProjectionMatrix();

            this.renderer.render(this.scene, this.camera);
        }
    }

    render() {
        return (
            <div>
                <div
                    id="boardCanvas"
                    style={{ width: "900px", height: "500px" }}
                    ref={mount => {
                        this.mount = mount;
                    }}
                />
            </div>
        );
    }
}

Do you mind demonstrating your issue with a live example?

@Audreyk you can use codesandbox.io to create live React examples.

Just a suggestion since you are using React. Highly recommend checking out react-three-fiber. It has this sort of thing handled for you. https://github.com/react-spring/react-three-fiber

1 Like

hello everyone! thanks a lot for your replies!

in the meantime, I found a solution by fixing the width and height to 100vw and 50vw, but of course let me know if you have other feedbacks/solutions.

here is the sandbox: https://codesandbox.io/s/elated-jones-ezhut

@sleekdigital yeah i heard about it, but i read online that it was still not well supported. Do you recommend?

i read online that it was still not well supported

Not sure what you mean, but it’s not a binding, r3f is a real reconciler: a different way to express threejs. It isn’t reliant on updates and maintenance when threejs alters/adds/remove features, and everything in threejs is supported. :wave:Author here :slight_smile:

What was that story, where two guys at the bar were trashing the book, and then it turns out one of them wrote it.

1 Like

it’s just someone that i read, not something i am assuming myself :slight_smile: it looks cool, i’ll check it out!

No worries. :slight_smile:

Hello, I dont know if it’s still related topic. But I just migrate to react three fiber and I found that the orbitControls behaviour a little bit different with the vanilla three js… minmaxpolarangle also the azimuth and the panning, maybe u can give me insight or give me the default setting of react three fiber

there are no orbit controls in r3f, if you use them they come from three/examples/jsm/… they shouldn’t behave differently if you have set them up in the same way as you’d have done in a vanilla project. but if you have a codesanbox i can take a look - who knows, maybe there is something that i messed up.

hello, I didn’t expect having that fast response from the author itself. Thank you for your time and sorry for the very late reply.

Here is the migrating https://codesandbox.io/s/learn-to-migrate-to-react-three-fiber-r8jgh
Here is the former react three only https://codesandbox.io/s/react-three-only-8e8z4

I added grid helpers just today, and found out my mesh flipped, I’ll try to fix it locally, but can u see my sandbox while I fix it? Maybe I messed up or maybe I missed some configurations for react three fiber. Thank youu

Btw, I love that I can imagine how short the code will be if I succesfully migrating this, and of course will have animation with react spring later on.

I’m pretty sure it is because the flipped mesh I messed up. A little bit more to solved. Sorry

it succeed, it is both my mistake to not know the case and the default camera.
If u want to take a look, here is the result.

Moreover, you can see the raycasting differences
thank you

there is no proper zorder raycasting in threejs unfortunately, ive opened a bug request for this once but it was closed: https://github.com/mrdoob/three.js/issues/16031

they consider the raycaster to be separate, it doesnt know about zorder, so you’re entirely on your own. if something works when two meshes are on top it’s happenstance. in r3f there’s a filter prop. we use that at work to even out such issues.

btw, if you fix ordering, there’s also event.stopPropagation(), that shuts up underlying meshes.

I mean if u take a look on https://codesandbox.io/s/react-three-only-8e8z4, the raycasting was way smoother. So I assume that u suggest to have like useThree() manually set raycasting like the way I did before?

Here’s my resize function if it is of any help… a div called container has the canvas…

		function onWindowResize() {
			var SCREEN_WIDTH = $(window).width() - 300;
			var SCREEN_HEIGHT = $(window).height() -150;
      $("#container").attr("width",SCREEN_WIDTH);
      $("#container").attr("height",SCREEN_HEIGHT);            
                            camera.position.set(0, 0, 10)
			camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
		camera.updateProjectionMatrix();
			renderer.setSize( SCREEN_WIDTH,SCREEN_HEIGHT );
		}

oh, then i think i misunderstood - i assumed its b/c some meshes seem to have the same z. perf problem must also have some reason behind it. there shouldn’t be any difference to raycasting manually.