Frontend dev's very interesting in my opinion. There's so much to learn, variety of challenges.
Because the requirements are so different. That being said, there's so many things to try out.
Probably people that are reading the post are already familiar with Three.js
a powerful 3d rendering library on the web browser.
I was known it's existance for quite sometime now, but never have felt the need to learn it.
However since I've started publishing my posts and started looking for things to learn. I have decided this was going to be One of the things I learned.
So here it goes. The react-three-fiber
tryout.
We should know that threejs came out not just for react. Since react has it's own rendering strategies we have to modify threejs codes to a React based
code.
Which means, we'll have to create components and divide the code and write stuff using JSX
which is the syntax React
uses.
Hence, we'll be using react-three-fiber
.
Threejs
If you're still unfamiliar to React
, probably should checkout React first.
As for threejs. These scene
, camera
, mesh
, geometry
, material
are the fundamentals to understand.
I didn't know the core concept of threejs, so let me elaborate.
There are somethings in Threejs for displaying "things" on the browser.
These elements are called scene
, camera
, renderer
.
Which means, in code term. In order to show something using Threejs there's always going to be a scene, camera, renderer code inside it.
Scene is where things are being displayed. You might say it's the background of the whole threejs rendering situation.
So camera object decide how the things that are displayed inside the scene are "seen". It decides the aspect ratio, if it feels near, far. tilted? It's like controling the eyeball.
There are many type of cameras that threejs offers. Usually these cameras are created using generators and they require attributes.
window.innerWidth / window.innerHeight
renderer is the one which combines everything, scene, camera and the things in scene, and draws this on the browser. Like its name it is in change of rendering the things. There is more than one renderer in threejs, for some people might not have WebGL support.
Now knowing this, let's look at this example code from three.js web.
the setSize
method of renderer as it's name can set the size of the rendering area. Which can affect the performance of the app.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
As you can see there's a scene
, camera
, renderer
.
Now we've seen how to create a scene and by now you'd probably noticed that the things we're interested in,
the objects that look 3d are created these Geometry
, Material
, Mesh
.
let's see another example code from the three.js website
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
look how Mesh
function takes Geometry and Material as argument.
In the end, scene.add()
is called and the Mesh object goes in as the argument.
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
In order for the scene to render, render.render()
must be called in a infinite loop.
Seems like the three.js library is recommending this by calling the animate
function to be called inside requestAnimationFrame;
So that was it. The basic understanding of three.js and the fundamentals of it.
Again, try to remember the names.
renderer.render()
Ther react-three-fiber library comes with a good example and actually the same example from threejs docs.
Since react uses jsx, creating a scene, light, camera, geometry, mesh it's all done with the jsx syntax.
let's have a look at the rendering scene first
import { Canvas } from "@react-three/fiber";
import Box from "components/Box";
<Canvas>
<ambientLight />
<pointLight position={[10, 10, 10]} />
<Box position={[-1.2, 0, 0]} />
<Box position={[1.2, 0, 0]} />
</Canvas>
<Canvas>
a given component is imported to carry its children JSX elements
Inside the Canvas there's a light
, and Box
which is obviously the Mesh
object.
So we can assume that, in @react-three/fiber the renderer, scene, camera is defaultly set inside <Canvas>
component(We'll have to dig about this later).
Also, the <ambientLight>
, <pointLight>
component doesn't even have import statements. We'll look into those too.
function Box(props: JSX.IntrinsicElements["mesh"]) {
const mesh = useRef<THREE.Mesh>(null!);
const [hovered, setHover] = useState(false);
const [active, setActive] = useState(false);
useFrame((state, delta) => (mesh.current.rotation.x += 0.01));
return (
<mesh
{...props}
ref={mesh}
scale={active ? 1.5 : 1}
onClick={(event) => setActive(!active)}
onPointerOver={(event) => setHover(true)}
onPointerOut={(event) => setHover(false)}
>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color={hovered ? "hotpink" : "orange"} />
</mesh>
);
}
Now having a look at the Mesh object, which has now beccome a react element
,
somethings are notable.
useRef
hook for the meshgeometry
and material
.@react-three/fiber
to animateDo you remember, in pure javascript code, mesh took geometry, material as arguments? Seems like in react it's now handled this way.
Alright, that's it for today.
Next time, we'll try to get the source code of space warping effect, and try to turn it into a react-based code.