3d·free
Hero Orb
Cursor-reactive floating distorted orb — a drop-in 3D hero backdrop.
Installation
terminal
pnpm add three @react-three/fiber @react-three/dreiThen copy the component below into src/components/three/hero-orb.tsx. It expects @/lib/gsap (plugin registration) and @/lib/utils (cn).
Source
src/components/three/hero-orb.tsx
"use client";
import { Suspense, useRef } from "react";
import { Canvas, useFrame } from "@react-three/fiber";
import { Float, MeshDistortMaterial, Environment, ContactShadows, Lightformer } from "@react-three/drei";
import type { Mesh } from "three";
import { cn } from "@/lib/utils";
export interface HeroOrbProps {
className?: string;
color?: string;
/** Surface distortion amount (0–1). */
distort?: number;
speed?: number;
wireframe?: boolean;
}
function Orb({ color, distort, speed, wireframe }: Required<Omit<HeroOrbProps, "className">>) {
const mesh = useRef<Mesh>(null);
useFrame((state) => {
if (!mesh.current) return;
const { x, y } = state.pointer;
mesh.current.rotation.x += (y * 0.4 - mesh.current.rotation.x) * 0.05;
mesh.current.rotation.y += (x * 0.6 - mesh.current.rotation.y) * 0.05;
});
return (
<Float speed={speed * 2} rotationIntensity={0.6} floatIntensity={1.2}>
<mesh ref={mesh} castShadow>
<icosahedronGeometry args={[1.6, 64]} />
<MeshDistortMaterial
color={color}
distort={distort}
speed={speed * 2}
roughness={0.15}
metalness={0.6}
wireframe={wireframe}
/>
</mesh>
</Float>
);
}
/** A floating, cursor-reactive distorted orb — drop-in 3D hero backdrop. */
export function HeroOrb({
className,
color = "#7c5cff",
distort = 0.45,
speed = 1,
wireframe = false,
}: HeroOrbProps) {
return (
<div className={cn("relative h-[480px] w-full", className)}>
<Canvas camera={{ position: [0, 0, 6], fov: 40 }} dpr={[1, 1.75]} gl={{ antialias: true, alpha: true }}>
<Suspense fallback={null}>
<ambientLight intensity={0.4} />
<directionalLight position={[4, 6, 4]} intensity={1.4} />
<Orb color={color} distort={distort} speed={speed} wireframe={wireframe} />
<ContactShadows position={[0, -2.2, 0]} opacity={0.5} blur={2.5} far={4} />
<Environment resolution={256}>
<Lightformer intensity={2} position={[0, 5, -6]} scale={[10, 4, 1]} />
<Lightformer intensity={1.5} color="#22d3ee" position={[-6, 2, 2]} rotation-y={Math.PI / 2} scale={[6, 3, 1]} />
<Lightformer intensity={1.5} color="#7c5cff" position={[6, -1, 2]} rotation-y={-Math.PI / 2} scale={[6, 3, 1]} />
</Environment>
</Suspense>
</Canvas>
</div>
);
}