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.
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.
onPointerOver: Fired when the pointer enters the object.onPointerOut: Fired when the pointer leaves the object.onClick: Fired when the object is clicked.onPointerMove: Fired when the pointer moves over the object.These handlers receive an event object that contains useful information, such as the intersected object, the point of intersection, and the original DOM event.
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.
@react-three/drei provide <TransformControls> or <DragControls> that handle the dragging logic for you.THREE.Frustum and THREE.Matrix4 to create a selection frustum and checking if object bounding boxes intersect with it.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>
);
}