A camera control for three.js, similar to THREE.OrbitControls yet supports smooth transitions and more features
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Customizable input handling for mouse, touch, and keyboard interactions with flexible action mapping and interactive area configuration.
Configure mouse button actions and wheel behavior for camera controls.
interface MouseButtons {
left: mouseButtonAction;
middle: mouseButtonAction;
right: mouseButtonAction;
wheel: mouseWheelAction;
}
// Mouse button action types
type mouseButtonAction =
| typeof ACTION.ROTATE
| typeof ACTION.TRUCK
| typeof ACTION.SCREEN_PAN
| typeof ACTION.OFFSET
| typeof ACTION.DOLLY
| typeof ACTION.ZOOM
| typeof ACTION.NONE;
type mouseWheelAction =
| typeof ACTION.ROTATE
| typeof ACTION.TRUCK
| typeof ACTION.SCREEN_PAN
| typeof ACTION.OFFSET
| typeof ACTION.DOLLY
| typeof ACTION.ZOOM
| typeof ACTION.NONE;
// Property
mouseButtons: MouseButtons;Usage Examples:
import CameraControls from 'camera-controls';
// Default configuration
console.log(cameraControls.mouseButtons);
// { left: ACTION.ROTATE, right: ACTION.TRUCK, middle: ACTION.DOLLY, wheel: ACTION.DOLLY }
// Custom mouse configuration
cameraControls.mouseButtons = {
left: CameraControls.ACTION.ROTATE, // Left drag = rotate
right: CameraControls.ACTION.TRUCK, // Right drag = pan
middle: CameraControls.ACTION.DOLLY, // Middle drag = dolly
wheel: CameraControls.ACTION.ZOOM // Wheel = zoom (not dolly)
};
// Disable right-click action
cameraControls.mouseButtons.right = CameraControls.ACTION.NONE;
// Alternative screen-pan for left button
cameraControls.mouseButtons.left = CameraControls.ACTION.SCREEN_PAN;Configure touch gesture actions for single, dual, and triple-finger interactions.
interface Touches {
one: singleTouchAction;
two: multiTouchAction;
three: multiTouchAction;
}
type singleTouchAction =
| typeof ACTION.TOUCH_ROTATE
| typeof ACTION.TOUCH_TRUCK
| typeof ACTION.TOUCH_SCREEN_PAN
| typeof ACTION.TOUCH_OFFSET
| typeof ACTION.DOLLY
| typeof ACTION.ZOOM
| typeof ACTION.NONE;
type multiTouchAction =
| typeof ACTION.TOUCH_DOLLY_ROTATE
| typeof ACTION.TOUCH_DOLLY_TRUCK
| typeof ACTION.TOUCH_DOLLY_OFFSET
| typeof ACTION.TOUCH_ZOOM_ROTATE
| typeof ACTION.TOUCH_ZOOM_TRUCK
| typeof ACTION.TOUCH_ZOOM_OFFSET
| typeof ACTION.TOUCH_DOLLY
| typeof ACTION.TOUCH_ZOOM
| typeof ACTION.TOUCH_ROTATE
| typeof ACTION.TOUCH_TRUCK
| typeof ACTION.TOUCH_SCREEN_PAN
| typeof ACTION.TOUCH_OFFSET
| typeof ACTION.NONE;
// Property
touches: Touches;Usage Examples:
// Default touch configuration
console.log(cameraControls.touches);
// { one: ACTION.TOUCH_ROTATE, two: ACTION.TOUCH_DOLLY_TRUCK, three: ACTION.TOUCH_TRUCK }
// Custom touch configuration
cameraControls.touches = {
one: CameraControls.ACTION.TOUCH_ROTATE, // One finger = rotate
two: CameraControls.ACTION.TOUCH_DOLLY_ROTATE, // Two fingers = pinch + rotate
three: CameraControls.ACTION.TOUCH_TRUCK // Three fingers = pan
};
// Pure two-finger dolly (no rotation)
cameraControls.touches.two = CameraControls.ACTION.TOUCH_DOLLY;
// Disable three-finger gestures
cameraControls.touches.three = CameraControls.ACTION.NONE;Define specific regions within the DOM element that respond to input events.
/**
* Set interactive area within the DOM element
* Values are normalized between 0 and 1, where:
* - 0 = left/top edge
* - 1 = right/bottom edge
*/
interactiveArea: DOMRect | {
x: number; // Left edge (0-1)
y: number; // Top edge (0-1)
width: number; // Width (0-1)
height: number; // Height (0-1)
};Usage Examples:
// Set interactive area to center 50% of canvas
cameraControls.interactiveArea = {
x: 0.25, // Start at 25% from left
y: 0.25, // Start at 25% from top
width: 0.5, // 50% width
height: 0.5 // 50% height
};
// Create full-screen interactive area (default)
cameraControls.interactiveArea = {
x: 0,
y: 0,
width: 1,
height: 1
};
// Bottom-right quadrant only
cameraControls.interactiveArea = {
x: 0.5,
y: 0.5,
width: 0.5,
height: 0.5
};
// Use DOMRect for pixel-perfect control
const rect = new DOMRect(100, 100, 400, 300);
cameraControls.interactiveArea = rect;All available action constants for input configuration.
const ACTION = {
// Basic actions
NONE: 0b0,
ROTATE: 0b1,
TRUCK: 0b10,
SCREEN_PAN: 0b100,
OFFSET: 0b1000,
DOLLY: 0b10000,
ZOOM: 0b100000,
// Touch-specific actions
TOUCH_ROTATE: 0b1000000,
TOUCH_TRUCK: 0b10000000,
TOUCH_SCREEN_PAN: 0b100000000,
TOUCH_OFFSET: 0b1000000000,
TOUCH_DOLLY: 0b10000000000,
TOUCH_ZOOM: 0b100000000000,
// Combined touch actions
TOUCH_DOLLY_TRUCK: 0b1000000000000,
TOUCH_DOLLY_SCREEN_PAN: 0b10000000000000,
TOUCH_DOLLY_OFFSET: 0b100000000000000,
TOUCH_DOLLY_ROTATE: 0b1000000000000000,
TOUCH_ZOOM_TRUCK: 0b10000000000000000,
TOUCH_ZOOM_OFFSET: 0b100000000000000000,
TOUCH_ZOOM_SCREEN_PAN: 0b1000000000000000000,
TOUCH_ZOOM_ROTATE: 0b10000000000000000000,
} as const;Mouse button identification constants for pointer events.
const MOUSE_BUTTON = {
LEFT: 1,
RIGHT: 2,
MIDDLE: 4,
} as const;
interface PointerInput {
pointerId: number;
clientX: number;
clientY: number;
deltaX: number;
deltaY: number;
mouseButton: MOUSE_BUTTON | null;
}Combined Gesture Examples:
// Two-finger pinch with rotation
cameraControls.touches.two = CameraControls.ACTION.TOUCH_DOLLY_ROTATE;
// Two-finger zoom with panning
cameraControls.touches.two = CameraControls.ACTION.TOUCH_ZOOM_TRUCK;
// Mouse wheel for rotation instead of dolly
cameraControls.mouseButtons.wheel = CameraControls.ACTION.ROTATE;
// Screen-space panning with middle mouse
cameraControls.mouseButtons.middle = CameraControls.ACTION.SCREEN_PAN;Action Type Explanations:
Platform-Specific Notes:
// Detect platform for context-specific configurations
const isMac = /Mac/.test(navigator.platform);
if (isMac) {
// Mac-specific touch configurations
cameraControls.touches.two = CameraControls.ACTION.TOUCH_ZOOM_ROTATE;
} else {
// PC/mobile configurations
cameraControls.touches.two = CameraControls.ACTION.TOUCH_DOLLY_TRUCK;
}Install with Tessl CLI
npx tessl i tessl/npm-camera-controls