A flexible drag-and-drop component for React Three Fiber + react-three-rapier
- Drag-and-Drop Physics: Physics-based dragging built on the
react-three-rapierphysics engine and a custom drag-controls implementation (CustomDragControls). - Customizable Bounding Box: Restrict object movement within defined boundaries.
- Wobbly effect: Optional spring joints provide "wobbly" effects for objects during and after drag events.
- Invisible Mesh for Control: Uses a hidden mesh to improve the precision and fluidity of dragging.
- Flexible Configuration: Easily configurable parameters for drag limits, joint stiffness, damping, and more.
This is not a published npm package. Download DraggableRigidBody.tsx and CustomDragControls.tsx from this repo and import them into your project.
The two files rely on the following runtime dependencies, which must already be installed in your project:
npm install three @react-three/fiber @react-three/rapier @react-three/drei @use-gesture/react@use-gesture/reactpowers the dragging logic inCustomDragControls.tsx.@react-three/dreiis used only for a TypeScript type helper (ForwardRefComponent); drei's ownDragControlsis not used.
CustomDragControls is a modified version of drei's DragControls that fixes overlaps (see this issue and this PR for additional info).
const DraggableRigidBodyProps: Partial<DraggableRigidBodyProps> = {
dragControlsProps: {
preventOverlap: true,
},
};Here's an example of how you can use the DraggableRigidBody component in your React Three Fiber scene:
function MyScene() {
const DraggableRigidBodyProps: Partial<DraggableRigidBodyProps> = {
rigidBodyProps: {
gravityScale: 3.5,
linearDamping: 5,
angularDamping: 0.2,
},
boundingBox: [
[-8, 8],
[0.5, 8],
[-8, 8],
],
dragControlsProps: {
preventOverlap: true,
},
};
return (
<Canvas>
<Physics>
<DraggableRigidBody
{...DraggableRigidBodyProps}
visibleMesh={
<mesh castShadow receiveShadow>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color={"gray"} wireframe={false} />
</mesh>
}
/>
</Physics>
</Canvas>
);
}| Prop Name | Type | Description |
|---|---|---|
visibleMesh |
ReactElement<ThreeElements['mesh']> |
The mesh visible in the scene. |
groupProps |
GroupProps |
Set position, rotation. |
boundingBox |
[[number, number], ...] |
Define min/max boundaries for dragging on the X, Y, and Z axes. |
dragControlsProps |
Partial<CustomDragControlsProps> |
Customize drag control behavior; set preventOverlap to true to avoid overlaps. |
rigidBodyProps |
RigidBodyProps |
Pass properties to the RigidBody component (e.g., mass, friction). |
invisibleMesh |
ReactElement<ThreeElements['mesh']> |
A mesh used for precise drag control but hidden in the scene. Defaults to visibleMesh. |
enableSpringJoint |
boolean |
Enable a spring joint for elastic drag behavior. |
jointConfig |
{ restLength, stiffness, damping, springJointCollisionGroups } |
Configure spring joint properties (rest length, stiffness, and damping). |
- React Three Fiber + three.js
- react-three-rapier (physics)
- @use-gesture/react (drag handling in
CustomDragControls) - drei (TypeScript type helper only)
- TypeScript
This is a work in progress! Take it as an example for your projects :)
