React Three Fiber — Creative Web

React Three Fiber React Three Fiber (R3F) adalah React renderer untuk Three.js. Daripada menulis kode Three.js imperatif, kamu mendeklarasikan scene 3D…

React Three Fiber

React Three Fiber (R3F) adalah React renderer untuk Three.js. Daripada menulis kode Three.js imperatif, kamu mendeklarasikan scene 3D menggunakan JSX — sama seperti menulis komponen React biasa.

Instalasi

npm install three @react-three/fiber @react-three/drei

Canvas Component — Entry Point

import { Canvas } from "@react-three/fiber";

function App() {
  return (
    <div style={{ width: "100vw", height: "100vh" }}>
      <Canvas>
        {/* Semua komponen 3D ditulis di sini */}
        <mesh>
          <boxGeometry args={[1, 1, 1]} />
          <meshStandardMaterial color="orange" />
        </mesh>
        <ambientLight intensity={0.5} />
        <directionalLight position={[5, 5, 5]} />
      </Canvas>
    </div>
  );
}

Perhatikan: Di R3F, semua class Three.js ditulis dalam camelCase sebagai JSX element:

Constructor arguments ditulis sebagai prop args={[...]}.

useFrame — Animation Hook

useFrame dipanggil setiap frame (60x per detik), sama seperti requestAnimationFrame:

import { useRef } from "react";
import { useFrame } from "@react-three/fiber";

function SpinningCube() {
  const meshRef = useRef();

  useFrame((state, delta) => {
    meshRef.current.rotation.x += delta;
    meshRef.current.rotation.y += delta * 0.5;
  });

  return (
    <mesh ref={meshRef}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color="#3498db" />
    </mesh>
  );
}

state berisi informasi scene (clock, camera, mouse, dll). delta adalah waktu sejak frame terakhir.

useThree — Akses Scene, Camera, dll

import { useThree } from "@react-three/fiber";

function CameraLogger() {
  const { camera, scene, gl, size } = useThree();

  console.log("Camera position:", camera.position);
  console.log("Canvas size:", size.width, size.height);

  return null; // komponen ini tidak render apa-apa
}

Drei Helpers — Komponen Siap Pakai

@react-three/drei menyediakan puluhan komponen berguna:

import {
  OrbitControls,
  Environment,
  Text,
  Float,
  MeshWobbleMaterial,
  RoundedBox,
  Stars,
} from "@react-three/drei";

function Scene() {
  return (
    <>
      {/* Kontrol kamera */}
      <OrbitControls enableDamping />

      {/* Environment lighting (HDRI) */}
      <Environment preset="sunset" />

      {/* Teks 3D */}
      <Text
        position={[0, 2, 0]}
        fontSize={0.5}
        color="white"
      >
        Hello R3F!
      </Text>

      {/* Objek yang melayang */}
      <Float speed={2} rotationIntensity={1} floatIntensity={2}>
        <mesh>
          <torusKnotGeometry args={[0.5, 0.15, 100, 16]} />
          <MeshWobbleMaterial color="#e74c3c" factor={0.5} speed={2} />
        </mesh>
      </Float>

      {/* Background bintang */}
      <Stars radius={100} depth={50} count={5000} />

      {/* Box dengan sudut membulat */}
      <RoundedBox args={[1, 1, 1]} radius={0.1}>
        <meshStandardMaterial color="#2ecc71" />
      </RoundedBox>
    </>
  );
}

Deklaratif vs Imperatif

Bandingkan Three.js murni vs R3F:

// Three.js imperatif
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: "red" });
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, 1, 0);
scene.add(mesh);
// R3F deklaratif
<mesh position={[0, 1, 0]}>
  <boxGeometry args={[1, 1, 1]} />
  <meshStandardMaterial color="red" />
</mesh>

R3F jauh lebih ringkas dan mengikuti mental model React — describe what you want, bukan how to do it.

Event Handling di R3F

R3F menangani Raycaster secara otomatis:

function InteractiveCube() {
  const [hovered, setHovered] = useState(false);
  const [clicked, setClicked] = useState(false);

  return (
    <mesh
      onPointerOver={() => setHovered(true)}
      onPointerOut={() => setHovered(false)}
      onClick={() => setClicked(!clicked)}
      scale={clicked ? 1.5 : 1}
    >
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? "hotpink" : "orange"} />
    </mesh>
  );
}

Tidak perlu Raycaster manual! R3F menyediakan event props yang familiar: onClick, onPointerOver, onPointerOut, onPointerMove, onPointerDown, onPointerUp.

Contoh Komponen Reusable

function FloatingShape({ geometry, color, position, speed = 1 }) {
  const ref = useRef();

  useFrame((state) => {
    ref.current.position.y = position[1] + Math.sin(state.clock.elapsedTime * speed) * 0.5;
    ref.current.rotation.y += 0.01;
  });

  return (
    <mesh ref={ref} position={position}>
      {geometry}
      <meshStandardMaterial color={color} roughness={0.3} />
    </mesh>
  );
}

// Penggunaan
<FloatingShape
  geometry={<sphereGeometry args={[0.5, 32, 32]} />}
  color="#e74c3c"
  position={[-2, 0, 0]}
  speed={1.5}
/>

R3F membuat 3D di web terasa natural bagi developer React — compose, reuse, dan manage state dengan cara yang sudah familiar.