← Back

Creating Animated Backgrounds in React with React Three Fiber

2024-10-11

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?

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!



Comments

Share your thoughts in the comments below!

No comments yet... You could be the first!