Creating a 3D starfield effect with React & Three
By Toby Gates - 19 February 2021
Introduction
In this article we are going to explore how to create a component with a 3D starfield type effect similar to the one on the homepage using React and Three.js.
Below is a demo of what we'll be building:
Demo:
Setting up the basic component
Before we get started on the component we'll need to install a few packages. The packages we'll be using are three
, @react-three/fiber
and @react-three/drei
.
three
(Three.js) is an easy to use, lightweight, 3D library with a default WebGL renderer.@react-three/fiber
is a React renderer for Three.js.@react-three/drei
is a collection of useful helpers and abstractions for@react-three/fiber
.
We can install these packages as follows:
npm install three @react-three/fiber @react-three/drei
Once the packages have been installed we're ready to create our component.
We'll start off with a basic React functional component and import the modules we need.
Then we need to include the Stars
element from @react-three/drei
and wrap it in the Canvas
element from @react-three/fiber
.
Code:
import React from 'react'
import { Canvas } from '@react-three/fiber'
import { Stars } from '@react-three/drei'
const Starfield = () => {
return (
<div className='stars'>
<Canvas>
<Stars />
</Canvas>
</div>
)
}
export default Starfield
This provides us with a very basic version of the starfield effect we are looking for.
Demo:
Note: For the sake of the demo, we've also add a background, height & margin so that the element is visible.
Animating the component
Next we need to look at how we can animate the component.
Let's setup a new functional component called RotatingStars
to return the Stars
component we imported earlier, and use it to replace the Stars
component wrapped in the Canvas
.
Code:
import React from 'react'
import { Canvas } from '@react-three/fiber'
import { Stars } from '@react-three/drei'
const RotatingStars = () => {
return <Stars />
}
const Starfield = () => {
return (
<div className='stars'>
<Canvas>
<RotatingStars />
</Canvas>
</div>
)
}
export default Starfield
Now that Stars
is wrapped in it's own component, we are able to manipulate that element.
The useFrame
hook provided by @react-three/fiber
will allow us to hook the component into the render-loop.
We will also need a way of letting React know which element we'll be animating so we'll need to import the useRef
hook.
import React, { useRef } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'
import { Stars } from '@react-three/drei'
In our RotatingStars
function, let's create a ref and attach it to the Stars
component.
const RotatingStars = () => {
const stars = useRef()
return <Stars ref={stars} />
}
Now we have a reference to the element we can update its rotation on each render of the render-loop using the useFrame
hook.
const RotatingStars = () => {
const stars = useRef()
useFrame(() => {
stars.current.rotation.x = stars.current.rotation.y += 0.00015
})
return <Stars ref={stars} />
}
Here we've set the x
rotation to be slightly offset from the y
rotation - giving us the slow spinning effect.
You should now have something that looks like this:
Code:
import React, { useRef } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'
import { Stars } from '@react-three/drei'
const Starfield = () => {
const RotatingStars = () => {
const stars = useRef()
useFrame(() => {
stars.current.rotation.x = stars.current.rotation.y += 0.00015
})
return <Stars ref={stars} />
}
return (
<div className='stars'>
<Canvas>
<RotatingStars />
</Canvas>
</div>
)
}
export default Starfield
Demo:
Movement Controls
On the version on the homepage there is a button to allow a '3D orbit' type effect. This can be achieved using OrbitControls
component included in the @react-three/drei
package.
It's simply a matter of importing the component and wrapping it within the Canvas
component.
import { Stars, OrbitControls } from '@react-three/drei'
return (
<div className='stars'>
<Canvas>
<OrbitControls />
<RotatingStars />
</Canvas>
</div>
)
This gives us the orbit controls as shown in the demo below:
Demo:
Note: The 'Explore Space!' button on the homepage toggles an
orbit
state which in turn toggles theOrbitControls
component on and off.
Conclusion
Hopefully this article has given you a brief understanding of how to setup a very basic @react-three/fiber
component while also creating a fun effect that you can use in your projects.