Spherical camera controller for Three.js
npm install @masatomakino/threejs-spherical-controls --save-dev
import { SphericalController, generateCameraTarget } from "@masatomakino/threejs-spherical-controls";
import { Spherical, Vector3 } from "three";
import { Easing } from "@tweenjs/tween.js";
// Create camera target (invisible sphere that camera looks at)
const cameraTarget = generateCameraTarget();
scene.add(cameraTarget);
// Initialize controller
const controller = new SphericalController(camera, cameraTarget);
// Set initial position (radius: 50, phi: near 0, theta: 0)
controller.initCameraPosition(new Spherical(50, 0.0001, 0));
// Move to new position with animation
controller.move(new Spherical(50, Math.PI / 2, Math.PI / 4), {
duration: 1500,
easing: Easing.Cubic.Out
});
// Listen for animation completion
controller.on("moved_camera_complete", (event) => {
console.log("Camera movement completed", event);
});
// Listen for animation updates
controller.on("moved_camera", (event) => {
console.log("Camera movement", event);
});
// Add to current position
controller.addPosition("radius", -10); // Move closer
controller.addPosition("phi", 0.1); // Rotate vertically
controller.addPosition("theta", 0.2); // Rotate horizontally
// Create continuous oscillation between two values
controller.loop("theta", -Math.PI/4, Math.PI/4, {
duration: 5000,
easing: Easing.Sinusoidal.InOut
});
// Stop loop animation
controller.stopLoop("theta");
// Set movement limits
controller.limiter.setLimit("phi", 0.1, Math.PI - 0.1); // Vertical limits
controller.limiter.setLimit("theta", -Math.PI, Math.PI); // Horizontal limits
controller.limiter.setLimit("radius", 10, 100); // Distance limits
// Shift camera position relative to target
controller.initCameraShift(new Vector3(0, 10, 0));
import {
SphericalController, // Main controller class
generateCameraTarget, // Utility to create camera target
EasingOption, // Animation options interface
SphericalControllerUtil, // Utility functions
CameraPositionUpdater, // Camera positioning logic
CameraPositionLimiter, // Position constraint logic
// ... and more
} from "@masatomakino/threejs-spherical-controls";
The controller uses spherical coordinates: