Hover, click, drag, selection logic

Back to Modules

Hover, Click, Drag, and Selection Logic in React Three Fiber

React Three Fiber (R3F) simplifies handling user interactions with 3D objects by integrating directly with React's event system. This allows you to use familiar event handlers like onPointerOver, onPointerOut, and onClick directly on your 3D components.

Hover and Click Interactions

R3F components expose pointer event handlers that work similarly to DOM events. When the user's mouse (or touch) interacts with a mesh, these events are triggered.

These handlers receive an event object that contains useful information, such as the intersected object, the point of intersection, and the original DOM event.

Drag and Selection Logic

Implementing drag and more complex selection (like marquee selection) often involves combining R3F's pointer events with state management and potentially external libraries or custom raycasting logic.

Example: Hover and Click on a Box

This example demonstrates how to change the color of a box on hover and log a message when it's clicked. Note that this requires a React environment to run.

import React, { useRef, useState } from 'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { OrbitControls } from '@react-three/drei';

function InteractiveBox(props) {
  const meshRef = useRef();
  const [hovered, setHover] = useState(false);
  const [clicked, setClick] = useState(false);

  // Simple rotation animation
  useFrame(() => {
    if (meshRef.current) {
      meshRef.current.rotation.x += 0.005;
      meshRef.current.rotation.y += 0.005;
    }
  });

  return (
    <mesh
      {...props}
      ref={meshRef}
      scale={clicked ? 1.2 : 1} // Scale up when clicked
      onClick={() => setClick(!clicked)}
      onPointerOver={() => setHover(true)}
      onPointerOut={() => setHover(false)}
    >
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  );
}

export default function App() {
  return (
    <Canvas camera={{ position: [0, 0, 3] }}>
      <ambientLight intensity={0.5} />
      <pointLight position={[10, 10, 10]} />
      <InteractiveBox />
      <OrbitControls />
    </Canvas>
  );
}