Jump into react and threejs to build shapes using react-three-fiber

Qurat-ul-Ain
4 min readApr 3, 2021

--

Today is an era of 3d modeling. I come across threejs while surfing and found it quite interesting. three.js is an open source JavaScript library for 3D graphics on the web. To render 3D models and animations for react applications, react-three-fiber is your best choice.
It handles stuff like scenes, camera views, lights, shadows, materials, textures and 3d math etc.

Let`s build some basic shapes in react application, so to make use of this library first create a simple react application and move into the application folder. Then you need to install threejs library for react.

npx create-react-app shapes-app
cd shapes-app
npm install three @react-three/fiber

Once, the packages are installed, start the development server using the command

npm start

we are going to build shapes like cube, sphere, circle and cone using react-three-fiber. Each shape will be a different component containing its own characteristics then all these components will be rendered into the main App component.

First step is to add some basic code into App component i.e. import useRef, useState from react. The useRef hook to access the mesh of the shape and the useState hook to check for the active state of the geometrical shape. Then import Canvas and useFrame from react-three-fiber, the canvas is used to draw the graphics on the browser, while the useFrame allows components to hook into the render-loop, so that one component can render over the content of another component.

import React, { useRef, useState } from "react";
import { Canvas, useFrame } from "@react-three/fiber";

To add a cool background effect of a solar space with movement on dragging clicked mouse, we will use OrbitControls and Stars component installed via “react-three-drei”

import { OrbitControls, Stars } from "@react-three/drei";

Next for us is to write logic for our Box component. First, we’ll start with building a functional component , let’s do that below.

function Box(props) {
const mesh = useRef();
const [hovered, setHover] = useState(false);
overhead
useFrame(() => {
mesh.current.rotation.x = mesh.current.rotation.y += 0.01;
});
return (
<mesh
{...props}
ref={mesh}
scale={[1, 1, 1]}
onPointerOver={(e) => setHover(true)}
onPointerOut={(e) => setHover(false)}>
<boxBufferGeometry />
<meshLambertMaterial color={hovered ? "purple" : "orange"} />
</mesh>
);
}

In the above code we use the useFrame hook from react-three-fiber to rotate the mesh every 0.01 sec , using the code below

mesh.current.rotation.x = mesh.current.rotation.y += 0.01;

Next, we want to render the Box component and add mesh, events and material. Mesh objects draw specific geometry with a specific material. Materials basically determine how the surface of our geometry is drawn in Three.js. for e.g if the geometry is skeleton of the object then the material is its skin. There are various materials in Three.js like basic, lambert, phong, or normal which responds to lights, mapping textures and adjusting opacity. meshLambertMaterial is applied to the outer surface of the mesh. In mesh scale property is used to set the size of the object. onPointOut and onPointOver are click events to enable hover effects on our objects.

Below is the code to draw Sphere and Circle

// Draw Sphere
function Sphere(props) {
const mesh = useRef();

useFrame(() => {
mesh.current.rotation.x = mesh.current.rotation.y += 0.01;
});
return (
<mesh ref={mesh} position={[1.2, 0, 0]}>
<sphereGeometry
attach="geometry"
args={[1, 22, 50]} // Width, Height and Depth of the sphere
smoothness={5}
{...props}
/>
<meshPhongMaterial
color="darkred"
attach="material"
transparent
roughness={0.1}
metalness={0.1}
/>
</mesh>
);
}
//draw Circlefunction CircleShape(props) {
const mesh = useRef();
useFrame(() => {
mesh.current.rotation.y = mesh.current.rotation.x += 0.01;
});
return (
<mesh ref={mesh} scale={[3, 3, 3]} position={[1.2, 0, 0]}>
<circleBufferGeometry attach="geometry" args={[0.5, 100]} /> <meshNormalMaterial attach="material" />
</mesh>
);
}

Notice in the above code that position(x,y,z) coordinates of the mesh are kept the same in Sphere and Circle, so the shapes are overlapping.

Now, we will write logic for a ConeShape component which is similar to the above mentioned components.

function ConeShape(props) {
const mesh = useRef();
useFrame(() => {
mesh.current.rotation.y = mesh.current.rotation.x -= 0.01;
});
return (
<mesh ref={mesh} position={[3.5, -0.5, 0]} scale={(0.5, 0.5, 0.8)}>
<coneGeometry
attach="geometry"
args={[1, 2.5, 3]}
smoothness={5}
{...props}/>
<meshPhongMaterial
color="green"
attach="material"
transparent
roughness={0.1}
metalness={0.1}/>
</mesh>
);
}

Next, we want to render the Box, Sphere, CircleShape and ConeShape component on the browser , so we include these components in our App.js component. Open your App component and add a Canvas tag, this is to render our 3D models. let’s do that below

export default function App() {

return (
<Canvas>
<OrbitControls />
<Stars />
<ambientLight intensity={0.4} />
<spotLight position={[30, 30, 10]} />
<Box position={[-3.5,-0.4, 0]} />
<Sphere />
<CircleShape />
<ConeShape />
</Canvas>
);
}

In the above code ambient light is used to light all objects in a scene or model equally, spot light is emitted from a single direction, point light comes from a particular point on one side and position attribute is used to used to set the position of the object on the canvas.

Get the code : Qurat62/shapesThreejs (github.com)

Reference links:

--

--