Useful add-ons for react-three-fiber providing 100+ components for 3D web applications
—
High-level components for common 3D elements like text, images, audio, and geometric shapes. These components provide easy-to-use interfaces for complex Three.js functionality.
2D text rendering with font support, alignment options, and material properties.
/**
* 2D text rendering with font support
* @param props - Text configuration props
* @returns JSX element for the text mesh
*/
function Text(props: TextProps): JSX.Element;
interface TextProps extends Omit<ThreeElements['mesh'], 'ref'> {
/** Text content */
children: React.ReactNode;
/** Characters to preload for performance */
characters?: string;
/** Text color */
color?: ReactThreeFiber.Color;
/** Font size, 1 */
fontSize?: number;
/** Font weight */
fontWeight?: number | string;
/** Font style */
fontStyle?: 'italic' | 'normal';
/** Maximum width before wrapping */
maxWidth?: number;
/** Line height multiplier */
lineHeight?: number;
/** Letter spacing */
letterSpacing?: number;
/** Text alignment */
textAlign?: 'left' | 'right' | 'center' | 'justify';
/** Font URL or data */
font?: string;
/** Anchor X position, 'center' */
anchorX?: number | 'left' | 'center' | 'right';
/** Anchor Y position, 'middle' */
anchorY?: number | 'top' | 'top-baseline' | 'middle' | 'bottom-baseline' | 'bottom';
/** Clip bounding box */
clipRect?: [number, number, number, number];
/** Depth offset for z-fighting, 0 */
depthOffset?: number;
/** Text direction, 'auto' */
direction?: 'auto' | 'ltr' | 'rtl';
/** Overflow wrapping */
overflowWrap?: 'normal' | 'break-word';
/** White space handling */
whiteSpace?: 'normal' | 'overflowWrap' | 'nowrap';
/** Outline width */
outlineWidth?: number | string;
/** Outline X offset */
outlineOffsetX?: number | string;
/** Outline Y offset */
outlineOffsetY?: number | string;
/** Outline blur */
outlineBlur?: number | string;
/** Outline color */
outlineColor?: ReactThreeFiber.Color;
/** Outline opacity, 1 */
outlineOpacity?: number;
/** Stroke width */
strokeWidth?: number | string;
/** Stroke color */
strokeColor?: ReactThreeFiber.Color;
/** Stroke opacity, 1 */
strokeOpacity?: number;
/** Fill opacity, 1 */
fillOpacity?: number;
/** SDF glyph size, 64 */
sdfGlyphSize?: number;
/** Enable SDF debugging */
debugSDF?: boolean;
/** Glyph geometry detail */
glyphGeometryDetail?: number;
/** Sync callback */
onSync?: (troika: any) => void;
}Usage Examples:
import { Text } from '@react-three/drei';
// Basic text
<Text fontSize={2} color="hotpink">
Hello World
</Text>
// Advanced text with styling
<Text
fontSize={1}
color="#333"
font="/fonts/roboto.json"
textAlign="center"
anchorX="center"
anchorY="middle"
maxWidth={10}
lineHeight={1.2}
letterSpacing={0.1}
outlineWidth={0.05}
outlineColor="white"
>
Styled Text with Outline
</Text>3D extruded text with depth and bevel options.
/**
* 3D extruded text rendering
* @param props - 3D text configuration props
* @returns JSX element for the 3D text mesh
*/
function Text3D(props: Text3DProps): JSX.Element;
interface Text3DProps extends Omit<ThreeElements['mesh'], 'ref'> {
/** Text content */
children: React.ReactNode;
/** Font URL or font object */
font: string | FontData;
/** Font size, 1 */
size?: number;
/** Extrusion depth, 0.2 */
height?: number;
/** Curve segments, 12 */
curveSegments?: number;
/** Enable bevel, false */
bevelEnabled?: boolean;
/** Bevel thickness, 0.1 */
bevelThickness?: number;
/** Bevel size, 0.05 */
bevelSize?: number;
/** Bevel offset, 0 */
bevelOffset?: number;
/** Bevel segments, 3 */
bevelSegments?: number;
/** Line height, 1 */
lineHeight?: number;
/** Letter spacing, 0 */
letterSpacing?: number;
/** Smooth rendering, false */
smooth?: number;
}Usage Examples:
import { Text3D } from '@react-three/drei';
// Basic 3D text
<Text3D font="/fonts/helvetiker_regular.json">
3D Text
<meshNormalMaterial />
</Text3D>
// 3D text with bevel
<Text3D
font="/fonts/helvetiker_bold.json"
size={2}
height={0.5}
bevelEnabled
bevelThickness={0.1}
bevelSize={0.05}
bevelSegments={5}
curveSegments={8}
>
Beveled Text
<meshStandardMaterial color="gold" />
</Text3D>Image display component with transparency support and aspect ratio management.
/**
* Image display with transparency support
* @param props - Image configuration props
* @returns JSX element for the image plane
*/
function Image(props: ImageProps): JSX.Element;
interface ImageProps extends Omit<ThreeElements['mesh'], 'ref'> {
/** Image URL or texture */
url?: string;
/** Image texture */
texture?: Texture;
/** Image segments [x, y], [1, 1] */
segments?: [number, number];
/** Image scale */
scale?: number | [number, number];
/** Image color */
color?: ReactThreeFiber.Color;
/** Image opacity, 1 */
opacity?: number;
/** Transparent rendering, true */
transparent?: boolean;
/** Side rendering, FrontSide */
side?: Side;
/** Zoom factor, 1 */
zoom?: number;
/** Radius for rounded corners, 0 */
radius?: number;
/** Grayscale amount, 0 */
grayscale?: number;
/** Tone mapping, false */
toneMapped?: boolean;
}Usage Examples:
import { Image } from '@react-three/drei';
// Basic image
<Image url="/textures/photo.jpg" />
// Styled image with effects
<Image
url="/textures/logo.png"
scale={[2, 1]}
opacity={0.8}
transparent
radius={0.1}
grayscale={0.3}
position={[0, 1, 0]}
/>3D positional audio component with distance-based volume and directional sound.
/**
* 3D positional audio with distance-based volume
* @param props - Positional audio configuration
* @returns JSX element for the audio source
*/
function PositionalAudio(props: PositionalAudioProps): JSX.Element;
interface PositionalAudioProps extends Omit<ThreeElements['positionalAudio'], 'ref'> {
/** Audio URL or buffer */
url: string | AudioBuffer;
/** Audio distance model, 'inverse' */
distanceModel?: 'linear' | 'inverse' | 'exponential';
/** Maximum audio distance, 10000 */
maxDistance?: number;
/** Reference distance, 1 */
refDistance?: number;
/** Rolloff factor, 1 */
rolloffFactor?: number;
/** Inner cone angle, 360 */
coneInnerAngle?: number;
/** Outer cone angle, 0 */
coneOuterAngle?: number;
/** Outer cone gain, 0 */
coneOuterGain?: number;
/** Audio volume, 1 */
volume?: number;
/** Auto-play audio, false */
autoplay?: boolean;
/** Loop audio, false */
loop?: boolean;
/** Helper visualization, false */
helper?: boolean;
/** Load event handler */
onLoad?: (audio: PositionalAudio) => void;
/** Progress event handler */
onProgress?: (event: ProgressEvent) => void;
/** Error event handler */
onError?: (error: ErrorEvent) => void;
}Usage Examples:
import { PositionalAudio } from '@react-three/drei';
// Basic positional audio
<PositionalAudio
url="/audio/ambient.mp3"
distance={5}
loop
volume={0.5}
/>
// Directional audio with cone
<PositionalAudio
url="/audio/speech.wav"
distanceModel="linear"
maxDistance={20}
refDistance={1}
rolloffFactor={2}
coneInnerAngle={90}
coneOuterAngle={180}
coneOuterGain={0.1}
helper
onLoad={(audio) => console.log('Audio loaded', audio)}
/>Component that always faces the camera, useful for labels, sprites, and UI elements.
/**
* Component that always faces the camera
* @param props - Billboard configuration props
* @returns JSX element that rotates to face camera
*/
function Billboard(props: BillboardProps): JSX.Element;
interface BillboardProps extends Omit<ThreeElements['group'], 'ref'> {
/** Follow mode: true, 'x', 'y', 'z' */
follow?: boolean | 'x' | 'y' | 'z';
/** Lock X axis, false */
lockX?: boolean;
/** Lock Y axis, false */
lockY?: boolean;
/** Lock Z axis, false */
lockZ?: boolean;
}Usage Examples:
import { Billboard, Text } from '@react-three/drei';
// Text that always faces camera
<Billboard>
<Text fontSize={1} color="white">
Label
</Text>
</Billboard>
// Billboard with axis constraints
<Billboard follow="y" lockX>
<mesh>
<planeGeometry args={[2, 1]} />
<meshBasicMaterial color="red" />
</mesh>
</Billboard>Various line rendering components for curves and paths.
/**
* Generic line rendering component
* @param props - Line configuration props
* @returns JSX element for the line
*/
function Line(props: LineProps): JSX.Element;
/**
* Quadratic Bezier curve line
* @param props - Quadratic Bezier line props
* @returns JSX element for the curve
*/
function QuadraticBezierLine(props: QuadraticBezierLineProps): JSX.Element;
/**
* Cubic Bezier curve line
* @param props - Cubic Bezier line props
* @returns JSX element for the curve
*/
function CubicBezierLine(props: CubicBezierLineProps): JSX.Element;
/**
* Catmull-Rom spline line
* @param props - Catmull-Rom line props
* @returns JSX element for the spline
*/
function CatmullRomLine(props: CatmullRomLineProps): JSX.Element;
interface LineProps extends Omit<ThreeElements['line'], 'ref'> {
/** Line points */
points: Vector3[] | [number, number, number][];
/** Line color */
color?: ReactThreeFiber.Color;
/** Line width, 1 */
lineWidth?: number;
/** Dashed line pattern */
dashed?: boolean;
/** Dash size, 1 */
dashSize?: number;
/** Gap size, 1 */
gapSize?: number;
/** Vertex colors */
vertexColors?: boolean;
}
interface QuadraticBezierLineProps extends Omit<LineProps, 'points'> {
/** Start point */
start: Vector3 | [number, number, number];
/** End point */
end: Vector3 | [number, number, number];
/** Control point */
mid: Vector3 | [number, number, number];
/** Curve segments, 20 */
segments?: number;
}
interface CubicBezierLineProps extends Omit<LineProps, 'points'> {
/** Start point */
start: Vector3 | [number, number, number];
/** End point */
end: Vector3 | [number, number, number];
/** First control point */
midA: Vector3 | [number, number, number];
/** Second control point */
midB: Vector3 | [number, number, number];
/** Curve segments, 20 */
segments?: number;
}
interface CatmullRomLineProps extends Omit<LineProps, 'points'> {
/** Curve points */
points: Vector3[] | [number, number, number][];
/** Curve type, 'centripetal' */
curveType?: 'centripetal' | 'chordal' | 'catmullrom';
/** Curve tension, 0.5 */
tension?: number;
/** Closed curve, false */
closed?: boolean;
/** Curve segments, 20 */
segments?: number;
}Usage Examples:
import { Line, QuadraticBezierLine, CubicBezierLine, CatmullRomLine } from '@react-three/drei';
// Basic line
<Line
points={[[0, 0, 0], [1, 1, 0], [2, 0, 0]]}
color="red"
lineWidth={2}
/>
// Quadratic Bezier curve
<QuadraticBezierLine
start={[0, 0, 0]}
end={[2, 0, 0]}
mid={[1, 2, 0]}
color="blue"
lineWidth={3}
/>
// Cubic Bezier curve
<CubicBezierLine
start={[0, 0, 0]}
end={[3, 0, 0]}
midA={[1, 1, 0]}
midB={[2, -1, 0]}
color="green"
segments={50}
/>
// Catmull-Rom spline
<CatmullRomLine
points={[[0, 0, 0], [1, 2, 0], [2, -1, 0], [3, 1, 0]]}
curveType="centripetal"
tension={0.5}
color="purple"
closed
/>// Label that always faces camera
<Billboard>
<Text fontSize={0.5} color="white" anchorX="center" anchorY="middle">
Player Name
</Text>
</Billboard>function ResponsiveImage({ url }) {
const { viewport } = useThree();
return (
<Image
url={url}
scale={[viewport.width / 4, viewport.height / 4]}
/>
);
}function InteractiveAudio() {
const [playing, setPlaying] = useState(false);
const audioRef = useRef();
const togglePlay = () => {
if (audioRef.current) {
playing ? audioRef.current.pause() : audioRef.current.play();
setPlaying(!playing);
}
};
return (
<>
<PositionalAudio
ref={audioRef}
url="/audio/music.mp3"
distance={10}
volume={0.7}
onLoad={togglePlay}
/>
<mesh onClick={togglePlay}>
<sphereGeometry args={[0.5]} />
<meshStandardMaterial color={playing ? "green" : "red"} />
</mesh>
</>
);
}Component that positions children in screen space, following the camera.
/**
* Positions children in screen space, following the camera
* @param props - ScreenSpace configuration props
* @returns JSX element that follows camera position and rotation
*/
function ScreenSpace(props: ScreenSpaceProps): JSX.Element;
interface ScreenSpaceProps extends Omit<ThreeElements['group'], 'ref'> {
/** Depth offset from camera, -1 */
depth?: number;
}Post-processing effects wrapper component for shader effects.
/**
* Post-processing effects wrapper using EffectComposer
* @param props - Effects configuration props
* @returns JSX element for effect composition
*/
function Effects(props: EffectsProps): JSX.Element;
interface EffectsProps extends Omit<ThreeElements['effectComposer'], 'ref' | 'args'> {
/** Multisampling level, 8 */
multisamping?: number;
/** Color space */
colorSpace?: ColorSpace;
/** Texture data type */
type?: TextureDataType;
/** Render pass index, 1 */
renderIndex?: number;
/** Disable gamma correction, false */
disableGamma?: boolean;
/** Disable render pass, false */
disableRenderPass?: boolean;
/** Disable rendering, false */
disableRender?: boolean;
/** Enable depth buffer, true */
depthBuffer?: boolean;
/** Enable stencil buffer, false */
stencilBuffer?: boolean;
/** Texture anisotropy, 1 */
anisotropy?: number;
}Component that creates motion trail effects behind moving objects.
/**
* Creates motion trail effects behind moving objects
* @param props - Trail configuration props
* @returns JSX element for trail rendering
*/
function Trail(props: TrailProps): JSX.Element;
interface TrailProps extends Omit<ThreeElements['mesh'], 'ref'> {
/** Trail width, 0.2 */
width?: number;
/** Trail length, 1 */
length?: number;
/** Trail decay, 1 */
decay?: number;
/** Trail attenuation, (width) => width */
attenuation?: (width: number) => number;
/** Use local coordinates, false */
local?: boolean;
/** Target object to follow */
target?: React.RefObject<Object3D>;
}Component for efficiently creating copies of existing geometries and materials.
/**
* Efficiently creates copies of existing geometries and materials
* @param props - Clone configuration props
* @returns JSX element with cloned object
*/
function Clone(props: CloneProps): JSX.Element;
interface CloneProps extends Omit<ThreeElements['group'], 'ref'> {
/** Object to clone */
object: Object3D;
/** Clone children, false */
children?: boolean;
/** Transform injections */
inject?: any;
/** Cast shadows */
castShadow?: boolean;
/** Receive shadows */
receiveShadow?: boolean;
}Install with Tessl CLI
npx tessl i tessl/npm-react-three--drei