TL;DR: This post walks through how to build an animated dot background in React using React Three Fiber and Three.js. We'll cover the main concepts, walk through a working implementation, and show how to easily plug this into your own site.
Table of Contents:
- Why Use React Three Fiber?
- The Concept
- Installation
- Implementation Overview
- 1. Create the AnimatedDots Component
- 2. Wrap It in a Canvas
- 3. Add It to Your Layout
- Final Thoughts
Why Use React Three Fiber?
React Three Fiber is a powerful React renderer for Three.js that lets you build complex 3D scenes declaratively using JSX. This opens the door to easily integrating subtle animations and background effects into your site without sacrificing developer ergonomics.
The Concept
We'll create a floating dot background using a points
object in Three.js. Each point will be mapped with a circle texture and rotated slowly over time to create a calming animated visual.
This is based on the implementation in my AnimatedBackground.tsx
file, which lives in the components/
folder of this site.
Installation
To use React Three Fiber, you'll first need to install the dependencies:
npm install three @react-three/fiber @react-three/drei
Implementation Overview
Let's walk through how this is set up.
1. Create the AnimatedDots
Component
We'll use a buffer geometry to render hundreds of particles. A texture is applied to give each point a circular shape (defaults to a square).
import { Canvas, useLoader } from '@react-three/fiber';
import { OrbitControls } from '@react-three/drei';
import { useRef } from 'react';
import { useFrame } from '@react-three/fiber';
import * as THREE from 'three';
import { TextureLoader } from 'three';
function AnimatedDots() {
const ref = useRef<THREE.Points>(null);
const circleTexture = useLoader(TextureLoader, '/circle.png');
const numPoints = 400;
const positions = useRef(Float32Array.from({ length: numPoints * 3 }, () => (Math.random() - 0.5) * 10));
useFrame(({ clock }) => {
if (!ref.current) return;
const time = clock.getElapsedTime();
ref.current.rotation.y = time * 0.04;
ref.current.rotation.x = time * 0.01;
});
return (
<points ref={ref}>
<bufferGeometry>
<bufferAttribute
attach="attributes-position"
args={[positions.current, 3]}
/>
</bufferGeometry>
<pointsMaterial
map={circleTexture}
transparent
alphaTest={0.5}
size={0.065}
sizeAttenuation
color="#60a5fa"
/>
</points>
);
}
...
2. Wrap It in a Canvas
We use the Canvas
component from @react-three/fiber
to render the scene:
import { Canvas, useLoader } from '@react-three/fiber';
import { OrbitControls } from '@react-three/drei';
...
export default function AnimatedBackground() {
return (
<div className="fixed inset-0 -z-50">
<Canvas camera={{ position: [0, 0, 6] }}>
<ambientLight intensity={0.6} />
<pointLight position={[10, 10, 10]} />
<AnimatedDots />
<OrbitControls enableZoom={false} enablePan={false} enableRotate={false} />
</Canvas>
</div>
);
}
3. Add It to Your Layout
import AnimatedBackground from '@/components/AnimatedBackground';
export default function Layout({ children }) {
return (
<>
<AnimatedBackground />
<main>{children}</main>
</>
);
}
Just make sure your /public
directory includes a small circular image like circle.png
for the particle texture.
Final Thoughts
This animated background adds subtle visual flair and can be easily extended with different shapes, colors, and motion styles. React Three Fiber lets you keep everything React-style while tapping into the full power of Three.js.
Play with particle count, rotation speed, and textures to make it your own!