Aller au contenu principal

Camera Control

1. Digest

Interactive camera control is essential for creating engaging 3D web experiences, and Three.js provides a comprehensive suite of control systems to handle various interaction patterns. This module explores seven different camera control schemes, each designed for specific use cases - from the versatile OrbitControls for examining objects from all angles, to PointerLockControls for creating first-person game experiences similar to Minecraft.

The examples progress from simple orbital camera movement to advanced implementations combining keyboard input with pointer locking. You'll learn how to implement TrackballControls for unrestricted rotation, FlyControls for spacecraft-like navigation, FirstPersonControls for ground-based exploration, and DragControls for direct object manipulation. Each control system has unique characteristics: some require delta time updates, others work with damping for smooth motion, and some lock the mouse pointer for immersive experiences.

By working through these implementations, you'll understand how to choose the right control scheme for your project, configure control parameters like zoom limits and rotation constraints, handle control events, and create custom keyboard controllers. The module demonstrates practical patterns like generating random colored boxes for testing camera movement, proper control initialization with renderer elements, and responsive camera updates on window resize.

2. What is the purpose

The purpose of this module is to equip developers with the knowledge to implement professional-grade camera interactions in Three.js applications. Understanding camera controls is crucial because they directly impact user experience - the difference between a frustrating interface and an intuitive one often comes down to choosing and configuring the right control scheme.

You'll learn to select appropriate control systems based on your application's needs: OrbitControls for product viewers and 3D model inspection, PointerLockControls for immersive games and virtual tours, DragControls for interactive object placement, and FlyControls for architectural walkthroughs. The module teaches you how to customize control behavior through parameters like movement speed, rotation constraints, and damping effects.

Beyond basic implementation, you'll gain practical skills in event handling (detecting when controls lock/unlock or drag starts/ends), creating custom keyboard input handlers, and integrating controls with animation loops. These skills are foundational for building any interactive 3D web application, from e-commerce product configurators to educational simulations and browser-based games.

3. Some code block and its explanation

Example 1: OrbitControls with Damping and Configuration

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

// Controls setup
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // Smooth, inertial movement
// controls.enableZoom = false; // Disable zoom
// controls.maxDistance = 20; // Maximum zoom out distance
// controls.minPolarAngle = Math.PI / 4; // Vertical angle limit
// controls.target.set(2, 0, 2); // Set camera focus point
// controls.autoRotate = true; // Auto-rotate around target
// controls.autoRotateSpeed = 1; // Rotation speed

// In animation loop
function draw() {
renderer.render(scene, camera);
controls.update(); // Required when damping is enabled
window.requestAnimationFrame(draw);
}

OrbitControls is the most commonly used control system in Three.js, perfect for examining objects from all angles. The enableDamping property adds smooth, natural-feeling motion with momentum. The control requires calling update() in the animation loop when damping is enabled. You can constrain camera movement with properties like maxDistance, minPolarAngle, and target, making it ideal for product viewers where you want to limit how users can view an object. The auto-rotate feature is particularly useful for showcase applications.

Example 2: PointerLockControls with Keyboard Movement

import { PointerLockControls } from "three/examples/jsm/controls/PointerLockControls.js";

// Controls setup
const controls = new PointerLockControls(camera, renderer.domElement);

controls.domElement.addEventListener("click", function () {
controls.lock(); // Lock pointer on click (ESC to exit)
});

controls.addEventListener("lock", function () {
console.log("Pointer locked");
});

controls.addEventListener("unlock", function () {
console.log("Pointer unlocked");
});

// Custom keyboard controller
const keyController = new KeyController();

function walk() {
if (keyController.keys["KeyW"] || keyController.keys["ArrowUp"]) {
controls.moveForward(0.02);
}
if (keyController.keys["KeyS"] || keyController.keys["ArrowDown"]) {
controls.moveForward(-0.02);
}
if (keyController.keys["KeyA"] || keyController.keys["ArrowLeft"]) {
controls.moveRight(-0.02);
}
if (keyController.keys["KeyD"] || keyController.keys["ArrowRight"]) {
controls.moveRight(0.02);
}
}

class KeyController {
constructor() {
this.keys = [];
window.addEventListener('keydown', (e) => {
this.keys[e.code] = true;
});
window.addEventListener('keyup', (e) => {
delete this.keys[e.code];
});
}
}

PointerLockControls creates first-person camera experiences similar to popular games like Minecraft. When activated, it hides the cursor and captures all mouse movement for camera rotation. The control system provides moveForward() and moveRight() methods that move the camera relative to its current direction, perfect for WASD keyboard controls. The custom KeyController class tracks which keys are currently pressed, allowing smooth continuous movement rather than discrete steps. This pattern is essential for creating immersive 3D games and virtual tours in the browser.

Example 3: DragControls for Direct Object Manipulation

import { DragControls } from "three/examples/jsm/controls/DragControls.js";

// Create array of meshes to be draggable
const geometry = new THREE.BoxGeometry(1, 1, 1);
const meshes = [];
for (let i = 0; i < 20; i++) {
material = new THREE.MeshStandardMaterial({
color: `rgb(
${50 + Math.floor(Math.random() * 205)},
${50 + Math.floor(Math.random() * 205)},
${50 + Math.floor(Math.random() * 205)}
)`
});
mesh = new THREE.Mesh(geometry, material);
mesh.position.x = (Math.random() - 0.5) * 5;
mesh.position.y = (Math.random() - 0.5) * 5;
mesh.position.z = (Math.random() - 0.5) * 5;
scene.add(mesh);
meshes.push(mesh);
}

// Controls setup with event listeners
const controls = new DragControls(meshes, camera, renderer.domElement);

controls.addEventListener("dragstart", function (event) {
console.log("Drag Start", event);
});

controls.addEventListener("dragend", function (event) {
console.log("Drag End", event);
});

DragControls enables direct manipulation of 3D objects through mouse interaction, providing an intuitive way for users to reposition objects in a scene. Unlike other control systems that move the camera, DragControls moves the objects themselves. You pass an array of meshes that should be draggable when initializing the controls. The control system automatically handles raycasting to detect which object is under the cursor and translates mouse movement into 3D position changes. Event listeners for dragstart and dragend allow you to respond to user interactions, making it possible to save positions, trigger animations, or validate placements. This is invaluable for applications like furniture arrangers, scene editors, or interactive educational tools.

Example 4: Control Systems Requiring Delta Time

import { FlyControls } from "three/examples/jsm/controls/FlyControls.js";

const controls = new FlyControls(camera, renderer.domElement);
// controls.rollSpeed = 0.05;
// controls.movementSpeed = 5;
// controls.dragToLook = true;

const clock = new THREE.Clock();

function draw() {
const delta = clock.getDelta();
renderer.render(scene, camera);
controls.update(delta); // Must pass delta time
window.requestAnimationFrame(draw);
}

FlyControls and FirstPersonControls differ from OrbitControls in a critical way: they require delta time to be passed to their update() method. Delta time represents the time elapsed since the last frame, ensuring that movement speed remains consistent regardless of frame rate. Without delta time, objects would move faster on high-refresh-rate monitors and slower on lower-end devices. FlyControls simulates spacecraft-like movement with six degrees of freedom, allowing rotation on all axes including roll. This control scheme is perfect for space simulators, drone cameras, or any scenario where the camera needs unrestricted movement through 3D space.