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
Movement boundaries, collision detection, camera constraints, and viewport management for controlled navigation and interaction limits.
Set movement boundaries to constrain camera position and target within defined areas.
/**
* Set boundary box for camera movement constraints
* @param box3 - Three.js Box3 defining movement boundaries (optional, null removes boundaries)
*/
setBoundary(box3?: THREE.Box3): void;
// Boundary behavior properties
boundaryFriction: number; // default: 0.0
boundaryEnclosesCamera: boolean; // default: falseUsage Examples:
import * as THREE from 'three';
// Create boundary box from min/max coordinates
const boundaryBox = new THREE.Box3(
new THREE.Vector3(-10, -5, -10), // min (x, y, z)
new THREE.Vector3(10, 15, 10) // max (x, y, z)
);
// Apply boundary constraints
cameraControls.setBoundary(boundaryBox);
// Configure boundary behavior
cameraControls.boundaryFriction = 0.3; // Add friction near boundaries
cameraControls.boundaryEnclosesCamera = true; // Keep camera inside boundary
// Remove boundaries
cameraControls.setBoundary();Boundary Property Details:
Configure collision detection with scene meshes to prevent camera from intersecting objects.
/**
* Array of Three.js objects to test for collision
* Camera will stop moving when it would intersect these objects
*/
colliderMeshes: THREE.Object3D[];Usage Examples:
// Add individual meshes for collision
const wallMesh = new THREE.Mesh(wallGeometry, wallMaterial);
const floorMesh = new THREE.Mesh(floorGeometry, floorMaterial);
cameraControls.colliderMeshes = [wallMesh, floorMesh];
// Add entire scene for collision (performance impact)
cameraControls.colliderMeshes = [scene];
// Remove collision detection
cameraControls.colliderMeshes = [];
// Add meshes dynamically
cameraControls.colliderMeshes.push(newObstacle);
// Filter out specific meshes
cameraControls.colliderMeshes = cameraControls.colliderMeshes.filter(
mesh => mesh.name !== 'excludedMesh'
);Performance Note: Collision detection uses 4 raycasters from camera corners and may impact performance with complex scenes. Use judiciously and consider mesh complexity.
Set viewport area within canvas for camera calculations and coordinate transformations.
/**
* Set viewport for camera calculations
* @param viewportOrX - Vector4 viewport or X coordinate
* @param y - Y coordinate (when first param is number)
* @param width - Viewport width (when first param is number)
* @param height - Viewport height (when first param is number)
*/
setViewport(
viewportOrX: THREE.Vector4 | number | null,
y?: number,
width?: number,
height?: number
): void;Usage Examples:
// Set viewport using Vector4 (x, y, width, height)
const viewport = new THREE.Vector4(100, 50, 800, 600);
cameraControls.setViewport(viewport);
// Set viewport using individual parameters
cameraControls.setViewport(100, 50, 800, 600);
// Full canvas viewport (reset)
cameraControls.setViewport(null);
// Multiple viewports example
const leftViewport = new THREE.Vector4(0, 0, 400, 600);
const rightViewport = new THREE.Vector4(400, 0, 400, 600);
// Switch between viewports
cameraControls.setViewport(leftViewport);
// ... render left view
cameraControls.setViewport(rightViewport);
// ... render right viewUtility methods for calculating appropriate camera distances for object fitting.
/**
* Calculate distance needed to fit a box in the camera view
* @param width - Box width
* @param height - Box height
* @param depth - Box depth
* @param cover - Whether to cover (true) or contain (false) the box
* @returns Distance value for dollyTo()
*/
getDistanceToFitBox(width: number, height: number, depth: number, cover?: boolean): number;
/**
* Calculate distance needed to fit a sphere in the camera view
* @param radius - Sphere radius
* @returns Distance value for dollyTo()
*/
getDistanceToFitSphere(radius: number): number;Usage Examples:
// Calculate distance to fit a box
const boxWidth = 10, boxHeight = 8, boxDepth = 6;
const distance = cameraControls.getDistanceToFitBox(boxWidth, boxHeight, boxDepth);
await cameraControls.dollyTo(distance, true);
// Calculate distance with cover mode (fills viewport)
const coverDistance = cameraControls.getDistanceToFitBox(
boxWidth, boxHeight, boxDepth, true
);
await cameraControls.dollyTo(coverDistance, true);
// Calculate distance for sphere
const sphereRadius = 5;
const sphereDistance = cameraControls.getDistanceToFitSphere(sphereRadius);
await cameraControls.dollyTo(sphereDistance, true);
// Use with object dimensions
const box = new THREE.Box3().setFromObject(mesh);
const size = box.getSize(new THREE.Vector3());
const fitDistance = cameraControls.getDistanceToFitBox(size.x, size.y, size.z);Control camera orientation and up vector for non-standard coordinate systems.
/**
* Update camera up vector based on current state
*/
updateCameraUp(): void;
/**
* Apply stored up vector to camera
*/
applyCameraUp(): void;Usage Examples:
// For Z-up coordinate systems (common in CAD/3D modeling)
camera.up.set(0, 0, 1); // Set Z-up before creating controls
cameraControls.updateCameraUp();
// After changing camera up vector during runtime
camera.up.set(0, 1, 0); // Back to Y-up
cameraControls.applyCameraUp();
// Custom up vector for tilted scenes
camera.up.set(0.5, 0.866, 0); // 30-degree tilt
cameraControls.updateCameraUp();Utility method for normalizing accumulated rotation values.
/**
* Normalize rotation angles to prevent accumulation issues
* @returns This CameraControls instance for chaining
*/
normalizeRotations(): CameraControls;Usage Example:
// Normalize after many rotations to prevent floating-point drift
cameraControls.normalizeRotations();
// Chain with other operations
cameraControls
.normalizeRotations()
.saveState(); // Save normalized stateAll constraint-related properties for reference:
// Distance constraints (PerspectiveCamera only)
minDistance: number; // default: Number.EPSILON
maxDistance: number; // default: Infinity
// Zoom constraints
minZoom: number; // default: 0.01
maxZoom: number; // default: Infinity
// Rotation constraints (radians)
minPolarAngle: number; // default: 0
maxPolarAngle: number; // default: Math.PI
minAzimuthAngle: number; // default: -Infinity
maxAzimuthAngle: number; // default: Infinity
// Boundary behavior
boundaryFriction: number; // default: 0.0
boundaryEnclosesCamera: boolean; // default: false
// Collision objects
colliderMeshes: THREE.Object3D[]; // default: []
// Behavior modifiers
infinityDolly: boolean; // default: falseAdvanced Constraint Examples:
// Lock camera to horizontal plane (no vertical rotation)
cameraControls.minPolarAngle = Math.PI / 2;
cameraControls.maxPolarAngle = Math.PI / 2;
// Limit rotation to 180-degree arc
cameraControls.minAzimuthAngle = -Math.PI / 2;
cameraControls.maxAzimuthAngle = Math.PI / 2;
// Create "zoom box" with soft boundaries
const zoomBoundary = new THREE.Box3(
new THREE.Vector3(-20, -10, -20),
new THREE.Vector3(20, 20, 20)
);
cameraControls.setBoundary(zoomBoundary);
cameraControls.boundaryFriction = 0.8; // Strong resistance at edges
// Infinite dolly for architectural walkthroughs
cameraControls.infinityDolly = true;
cameraControls.minDistance = 0.1;
cameraControls.maxDistance = 1000;Install with Tessl CLI
npx tessl i tessl/npm-camera-controls