Camera controls#

CameraControls moves a camera (or any object that carries one) from the pointer, touch, keyboard, gamepads, and WebXR controllers, with one update() call per frame. Its two modes, orbit and fly, share one state, so switching between them does not move the view. It is based on Spark's SparkControls, and adds a double-press slide.

Code: src/controls/CameraControls.ts (imports three.js only; nothing else in Radix imports it).

const controls = new CameraControls({
  canvas: renderer.domElement,
  object: camera,
  storageKey: "my-page",
  settings: { mode: "orbit" },
});
// Face a point and orbit around it
controls.lookAt(new THREE.Vector3(0, 0, 0));

renderer.setAnimationLoop(() => {
  controls.update(); // true when the camera moved
  renderer.render(scene, camera);
});

Modes and state#

The state is the object's pose plus distance. The orbit target lies that distance in front of the object (getTarget()). Fly mode turns about the camera; orbit mode turns about the target. Switching modes (controls.mode = "fly", or the F key) keeps the pose. Movement is in the object's parent frame, and turns are about object.up.

Inputflyorbit
left drag, one fingerlookorbit around the target
double press, then dragslide sideways, forward, and backthe same
right drag, two fingerspan (the scene follows the pointer)pan, scaled by the distance
wheel, middle drag, pinchmove forward and backzoom between minDistance and maxDistance
WASD / arrows, Q E, PgUp PgDnmove; move down / upthe same
Insert Delete, Home Endturn; look up / downorbit
gamepadleft stick moves, right stick looks, LB / RB move down / up, LT slow, RT fastthe same

Members#

MemberWhat it does
new CameraControls({ canvas, object, settings?, storageKey?, xr?, rig? })settings: the page's defaults over CameraControls.DEFAULTS. storageKey: saves this page's settings apart from other pages'. xr: renderer.xr. rig: the object the XR sticks move (default the object's parent)
update()applies the input since the last call; whether the object moved
mode"fly" or "orbit" (CameraControlsMode); settable
lookAt(target)faces a point and sets distance to it
getTarget(out?)the orbit target: distance in front of the object
distancethe orbit radius (default 2)
objectthe moved object; settable
enabledfalse ignores input (a gizmo drag sets it)
settingsthe current settings; assigning changes them without saving
set(partial)changes and saves settings
save({ personal? })saves the current settings
reset({ personal? })forgets saved settings: the page's, and with personal: true the personal ones too
onChangecalled after settings change (by set, reset, or the mode key)
pick(x, y) => Promise<Vector3 | undefined>: the point under a canvas position, in CSS pixels
xr, rigas in the constructor
dispose()removes the event listeners

Settings#

SettingDefaultWhat it does
mode"fly"the starting mode
moveSpeed1keys and sticks: meters per second
lookSpeed2keys and sticks: radians per second
pointerLookSpeed0.003radians per pixel dragged
pointerPanSpeed0.002meters per pixel panned or slid (orbit: per unit of distance)
zoomSpeed0.0015per wheel unit (a notch is about 100): meters (fly), or a factor of exp(zoomSpeed) (orbit)
minDistance, maxDistance0.05, 1000the orbit zoom range
fastMultiplier, slowMultiplier, capsMultiplier5, 0.2, 10Shift, Ctrl, and Caps Lock
invertLookX, invertLookYtrue on touch screenstouch screens drag the scene rather than the view
invertPan, invertZoom, invertStickYfalse
pointerLockfalsefly mode: a click captures the pointer
inertia0.15 s each{ look, move, pointerLook, pointerMove } (CameraControlsInertia): keys and sticks ramp, pointer glide; 0 for none
modeKey"KeyF"the key that switches mode ("" for none)
doublePress300milliseconds between two presses that make the second drag slide (0: never)
stickDeadZone0.1
xrMoveSpeed, xrTurnSpeed1, 4XR sticks

controls.settings starts from CameraControls.DEFAULTS, then the page's settings, then the saved settings.

Types: CameraControlsSettings, CameraControlsInertia, CameraControlsMode, and XrInput (the part of renderer.xr the controls read: isPresenting and getSession()).

/build/examples/splats/index.html binds every setting in its panel (examples/splats/controlsPane.ts). The checks are in test/gpu/controlsTests.ts.

Source: docs/controls.md