Spaces:
Sleeping
Sleeping
| # camera-controls | |
| A camera control for three.js, similar to THREE.OrbitControls yet supports smooth transitions and more features. | |
| [](https://www.npmjs.com/package/camera-controls) [](https://github.com/codespaces/new?template_repository=yomotsu%2Fcamera-controls) | |
| [documentation](https://yomotsu.github.io/camera-controls/classes/CameraControls) | |
| ## Examples | |
| | camera move | default user input (Configurable) | | |
| | --- | --- | | |
| | Orbit rotation | left mouse drag / touch: one-finger move | | |
| | Dolly | middle mouse drag, or mousewheel / touch: two-finger pinch-in or out | | |
| | Truck (Pan) | right mouse drag / touch: two-finger move or three-finger move | | |
| - [basic](https://yomotsu.github.io/camera-controls/examples/basic.html) | |
| - [fit-and-padding](https://yomotsu.github.io/camera-controls/examples/fit-and-padding.html) | |
| - [fit-to-rect](https://yomotsu.github.io/camera-controls/examples/fit-to-rect.html) | |
| - [fit-to-bounding-sphere](https://yomotsu.github.io/camera-controls/examples/fit-to-bounding-sphere.html) | |
| - [infinity dolly](https://yomotsu.github.io/camera-controls/examples/infinity-dolly.html) | |
| - [boundary](https://yomotsu.github.io/camera-controls/examples/boundary.html) | |
| - [focal offset](https://yomotsu.github.io/camera-controls/examples/focal-offset.html) | |
| - [click to set orbit point](https://yomotsu.github.io/camera-controls/examples/click-to-set-orbit-point.html) | |
| - [look in the point direction](https://yomotsu.github.io/camera-controls/examples/look-in-direction.html) | |
| - [viewport within the canvas](https://yomotsu.github.io/camera-controls/examples/viewport.html) | |
| - [multiple camera-controls and viewport](https://yomotsu.github.io/camera-controls/examples/multiple.html) | |
| - [z-up camera](https://yomotsu.github.io/camera-controls/examples/camera-up.html) | |
| - [orthographic](https://yomotsu.github.io/camera-controls/examples/orthographic.html) | |
| - [event attach / detach](https://yomotsu.github.io/camera-controls/examples/event-attach.html) | |
| - [user input config](https://yomotsu.github.io/camera-controls/examples/config.html) | |
| - [mouse drag with modifier keys](https://yomotsu.github.io/camera-controls/examples/mouse-drag-with-modifier-keys.html) | |
| - [combined gestures](https://yomotsu.github.io/camera-controls/examples/combined-gestures.html) | |
| - [keyboard events](https://yomotsu.github.io/camera-controls/examples/keyboard.html) | |
| - [rest and sleep events](https://yomotsu.github.io/camera-controls/examples/rest-and-sleep.html) | |
| - [changing the cursor](https://yomotsu.github.io/camera-controls/examples/cursor.html) | |
| - [collision](https://yomotsu.github.io/camera-controls/examples/collision.html) | |
| - [collision (custom)](https://yomotsu.github.io/camera-controls/examples/collision-custom.html) | |
| - [first-person](https://yomotsu.github.io/camera-controls/examples/first-person.html) | |
| - [third-person](https://yomotsu.github.io/meshwalk/examples/5_terrain.html) (with [meshwalk](https://github.com/yomotsu/meshwalk)) | |
| - [pointer lock](https://yomotsu.github.io/camera-controls/examples/pointer-lock.html) | |
| - [auto rotate](https://yomotsu.github.io/camera-controls/examples/auto-rotate.html) | |
| - [view offset translate](https://yomotsu.github.io/camera-controls/examples/view-offset.html) | |
| - [camera shake effect](https://yomotsu.github.io/camera-controls/examples/effect-shake.html) | |
| - [rotate with time duration and easing](https://yomotsu.github.io/camera-controls/examples/easing.html) (with [gsap](https://www.npmjs.com/package/gsap)) | |
| - [path animation](https://yomotsu.github.io/camera-controls/examples/path-animation.html) (with [gsap](https://www.npmjs.com/package/gsap)) | |
| - [complex transitions with `await`](https://yomotsu.github.io/camera-controls/examples/await-transitions.html) | |
| - [set view padding](https://yomotsu.github.io/camera-controls/examples/padding-with-view-offset.html) | |
| - [WebWorker (OffscreenCanvas)](https://yomotsu.github.io/camera-controls/examples/worker.html) | |
| - [outside of iframe dragging](https://yomotsu.github.io/camera-controls/examples/iframe.html) | |
| - [in react-three-fiber (simplest)](https://codesandbox.io/s/react-three-fiber-camera-controls-4jjor?file=/src/App.tsx) | |
| - [in react-three-fiber (drei official)](https://codesandbox.io/s/sew669) (see [doc](https://github.com/pmndrs/drei#cameracontrols)) | |
| ## Usage | |
| (The below code is for three.js users. If you use react-three-fiber (aka R3F), r3f-ready camera-controls is available on [@react-three/drei](https://github.com/pmndrs/drei#cameracontrols) | |
| ```javascript | |
| import * as THREE from 'three'; | |
| import CameraControls from 'camera-controls'; | |
| CameraControls.install( { THREE: THREE } ); | |
| // snip ( init three scene... ) | |
| const clock = new THREE.Clock(); | |
| const camera = new THREE.PerspectiveCamera( 60, width / height, 0.01, 1000 ); | |
| const cameraControls = new CameraControls( camera, renderer.domElement ); | |
| ( function anim () { | |
| // snip | |
| const delta = clock.getDelta(); | |
| const hasControlsUpdated = cameraControls.update( delta ); | |
| requestAnimationFrame( anim ); | |
| // you can skip this condition to render though | |
| if ( hasControlsUpdated ) { | |
| renderer.render( scene, camera ); | |
| } | |
| } )(); | |
| ``` | |
| ### Important! | |
| You *must install* three.js before using camera-controls. Not doing so will lead to runtime errors (undefined references to THREE). | |
| **Before creating a new CameraControls instance, call**: | |
| ```javascript | |
| CameraControls.install( { THREE: THREE } ); | |
| ``` | |
| You can then proceed to use CameraControls. | |
| Note: If you do not wish to use the entire three.js to reduce file size(tree-shaking for example), make a subset to install. | |
| ```js | |
| import { | |
| Vector2, | |
| Vector3, | |
| Vector4, | |
| Quaternion, | |
| Matrix4, | |
| Spherical, | |
| Box3, | |
| Sphere, | |
| Raycaster, | |
| } from 'three'; | |
| const subsetOfTHREE = { | |
| Vector2 : Vector2, | |
| Vector3 : Vector3, | |
| Vector4 : Vector4, | |
| Quaternion: Quaternion, | |
| Matrix4 : Matrix4, | |
| Spherical : Spherical, | |
| Box3 : Box3, | |
| Sphere : Sphere, | |
| Raycaster : Raycaster, | |
| }; | |
| CameraControls.install( { THREE: subsetOfTHREE } ); | |
| ``` | |
| ## Constructor | |
| `CameraControls( camera, domElement )` | |
| - `camera` is a `THREE.PerspectiveCamera` or `THREE.OrthographicCamera` to be controlled. | |
| - `domElement` is a `HTMLElement` for draggable area. (optional. if domElement is omitted here, can be connect later with `.connect()`) | |
| ## Terms | |
| ### Orbit rotations | |
| CameraControls uses Spherical Coordinates for orbit rotations. | |
| If your camera is Y-up, the Azimuthal angle will be the angle for y-axis rotation and the Polar angle will be the angle for vertical position. | |
|  | |
| ### Dolly vs Zoom | |
| - A Zoom involves changing the lens focal length. In three.js, zooming is actually changing the camera FOV, and the camera is stationary (doesn't move). | |
| - A Dolly involves physically moving the camera to change the composition of the image in the frame. | |
| See [the demo](https://github.com/yomotsu/camera-movement-comparison#dolly-vs-zoom) | |
| ## Properties | |
| | Name | Type | Default | Description | | |
| | ------------------------- | --------- | ----------- | ----------- | | |
| | `.camera` | `THREE.Perspective \| THREE.Orthographic` | N/A | The camera to be controlled | | |
| | `.enabled` | `boolean` | `true` | Whether or not the controls are enabled. | | |
| | `.active` | `boolean` | `false` | Returns `true` if the controls are active updating. | | |
| | `.currentAction` | `ACTION` | N/A | Getter for the current `ACTION`. | | |
| | `.distance` | `number` | N/A | Current distance. | | |
| | `.minDistance` | `number` | `Number.EPSILON` | Minimum distance for dolly. The value must be higher than `0` | | |
| | `.maxDistance` | `number` | `Infinity` | Maximum distance for dolly. | | |
| | `.minZoom` | `number` | `0.01` | Minimum camera zoom. | | |
| | `.maxZoom` | `number` | `Infinity` | Maximum camera zoom. | | |
| | `.polarAngle` | `number` | N/A | Current polarAngle in radians. | | |
| | `.minPolarAngle` | `number` | `0` | In radians. | | |
| | `.maxPolarAngle` | `number` | `Math.PI` | In radians. | | |
| | `.azimuthAngle` | `number` | N/A | current azimuthAngle in radians ¹. | | |
| | `.minAzimuthAngle` | `number` | `-Infinity` | In radians. | | |
| | `.maxAzimuthAngle` | `number` | `Infinity` | In radians. | | |
| | `.boundaryFriction` | `number` | `0.0` | Friction ratio of the boundary. | | |
| | `.boundaryEnclosesCamera` | `boolean` | `false` | Whether camera position should be enclosed in the boundary or not. | | |
| | `.smoothTime` | `number` | `0.25` | Approximate time in seconds to reach the target. A smaller value will reach the target faster. | | |
| | `.draggingSmoothTime` | `number` | `0.125` | The smoothTime while dragging. | | |
| | `.azimuthRotateSpeed` | `number` | `1.0` | Speed of azimuth rotation. | | |
| | `.polarRotateSpeed` | `number` | `1.0` | Speed of polar rotation. | | |
| | `.dollySpeed` | `number` | `1.0` | Speed of mouse-wheel dollying. | | |
| | `.truckSpeed` | `number` | `2.0` | Speed of drag for truck and pedestal. | | |
| | `.dollyToCursor` | `boolean` | `false` | `true` to enable Dolly-in to the mouse cursor coords. | | |
| | `.dollyDragInverted` | `boolean` | `false` | `true` to invert direction when dollying or zooming via drag. | | |
| | `.interactiveArea` | `DOMRect` | N/A | Set drag-start, touches and wheel enable area in the domElement. each values are between `0` and `1` inclusive, where `0` is left/top and `1` is right/bottom of the screen. | | |
| | `.colliderMeshes` | `array` | `[]` | An array of Meshes to collide with camera ². | | |
| | `.infinityDolly` | `boolean` | `false` | `true` to enable Infinity Dolly for wheel and pinch. Use this with `minDistance` and `maxDistance` ³. | | |
| | `.restThreshold` | `number` | `0.0025` | Controls how soon the `rest` event fires as the camera slows | | |
| 1. Every 360 degrees turn is added to `.azimuthAngle` value, which is accumulative. | |
| `360º = 360 * THREE.MathUtils.DEG2RAD = Math.PI * 2`, `720º = Math.PI * 4`. | |
| **Tip**: [How to normalize accumulated azimuthAngle?](#tips) | |
| 2. Be aware colliderMeshes may decrease performance. The collision test uses 4 raycasters from the camera since the near plane has 4 corners. | |
| 3. If the Dolly distance is less (or over) than the `minDistance` (or `maxDistance`), `infinityDolly` will keep the distance and pushes the target position instead. | |
| ## Events | |
| CameraControls instance emits the following events. | |
| To subscribe, use `cameraControl.addEventListener( 'eventname', function )`. | |
| To unsubscribe, use `cameraControl.removeEventListener( 'eventname', function )`. | |
| | Event name | Timing | | |
| | ------------------- | ------ | | |
| | `'controlstart'` | When the user starts to control the camera via mouse / touches. ¹ | | |
| | `'control'` | When the user controls the camera (dragging). | | |
| | `'controlend'` | When the user ends to control the camera. ¹ | | |
| | `'transitionstart'` | When any kind of transition starts, either user control or using a method with `enableTransition = true` | | |
| | `'update'` | When the camera position is updated. | | |
| | `'wake'` | When the camera starts moving. | | |
| | `'rest'` | When the camera movement is below `.restThreshold` ². | | |
| | `'sleep'` | When the camera end moving. | | |
| 1. `mouseButtons.wheel` (Mouse wheel control) does not emit `'controlstart'` and `'controlend'`. `mouseButtons.wheel` uses scroll-event internally, and scroll-event happens intermittently. That means "start" and "end" cannot be detected. | |
| 2. Due to damping, `sleep` will usually fire a few seconds after the camera _appears_ to have stopped moving. If you want to do something (e.g. enable UI, perform another transition) at the point when the camera has stopped, you probably want the `rest` event. This can be fine tuned using the `.restThreshold` parameter. See the [Rest and Sleep Example](https://yomotsu.github.io/camera-controls/examples/rest-and-sleep.html). | |
| ## User input config | |
| Working example: [user input config](https://yomotsu.github.io/camera-controls/examples/config.html) | |
| | button to assign | behavior | | |
| | --------------------- | -------- | | |
| | `mouseButtons.left` | `CameraControls.ACTION.ROTATE`* \| `CameraControls.ACTION.TRUCK` \| `CameraControls.ACTION.SCREEN_PAN` \| `CameraControls.ACTION.OFFSET` \| `CameraControls.ACTION.DOLLY` \| `CameraControls.ACTION.ZOOM` \| `CameraControls.ACTION.NONE` | | |
| | `mouseButtons.right` | `CameraControls.ACTION.ROTATE` \| `CameraControls.ACTION.TRUCK`* \| `CameraControls.ACTION.SCREEN_PAN` \| `CameraControls.ACTION.OFFSET` \| `CameraControls.ACTION.DOLLY` \| `CameraControls.ACTION.ZOOM` \| `CameraControls.ACTION.NONE` | | |
| | `mouseButtons.wheel` ¹ | `CameraControls.ACTION.ROTATE` \| `CameraControls.ACTION.TRUCK` \| `CameraControls.ACTION.SCREEN_PAN` \| `CameraControls.ACTION.OFFSET` \| `CameraControls.ACTION.DOLLY` \| `CameraControls.ACTION.ZOOM` \| `CameraControls.ACTION.NONE` | | |
| | `mouseButtons.middle` ² | `CameraControls.ACTION.ROTATE` \| `CameraControls.ACTION.TRUCK` \| `CameraControls.ACTION.SCREEN_PAN` \| `CameraControls.ACTION.OFFSET` \| `CameraControls.ACTION.DOLLY`* \| `CameraControls.ACTION.ZOOM` \| `CameraControls.ACTION.NONE` | | |
| 1. Mouse wheel event for scroll "up/down" on mac "up/down/left/right" | |
| 2. Mouse click on wheel event "button" | |
| - \* is the default. | |
| - The default of `mouseButtons.wheel` is: | |
| - `DOLLY` for Perspective camera. | |
| - `ZOOM` for Orthographic camera, and can't set `DOLLY`. | |
| | fingers to assign | behavior | | |
| | --------------------- | -------- | | |
| | `touches.one` | `CameraControls.ACTION.TOUCH_ROTATE`* \| `CameraControls.ACTION.TOUCH_TRUCK` \| `CameraControls.ACTION.TOUCH_SCREEN_PAN` \| `CameraControls.ACTION.TOUCH_OFFSET` \| `CameraControls.ACTION.DOLLY` | `CameraControls.ACTION.ZOOM` | `CameraControls.ACTION.NONE` | | |
| | `touches.two` | `ACTION.TOUCH_DOLLY_TRUCK` \| `ACTION.TOUCH_DOLLY_SCREEN_PAN` \| `ACTION.TOUCH_DOLLY_OFFSET` \| `ACTION.TOUCH_DOLLY_ROTATE` \| `ACTION.TOUCH_ZOOM_TRUCK` \| `ACTION.TOUCH_ZOOM_SCREEN_PAN` \| `ACTION.TOUCH_ZOOM_OFFSET` \| `ACTION.TOUCH_ZOOM_ROTATE` \| `ACTION.TOUCH_DOLLY` \| `ACTION.TOUCH_ZOOM` \| `CameraControls.ACTION.TOUCH_ROTATE` \| `CameraControls.ACTION.TOUCH_TRUCK` \| `CameraControls.ACTION.TOUCH_SCREEN_PAN` \| `CameraControls.ACTION.TOUCH_OFFSET` \| `CameraControls.ACTION.NONE` | | |
| | `touches.three` | `ACTION.TOUCH_DOLLY_TRUCK` \| `ACTION.TOUCH_DOLLY_SCREEN_PAN` \| `ACTION.TOUCH_DOLLY_OFFSET` \| `ACTION.TOUCH_DOLLY_ROTATE` \| `ACTION.TOUCH_ZOOM_TRUCK` \| `ACTION.TOUCH_ZOOM_SCREEN_PAN` \| `ACTION.TOUCH_ZOOM_OFFSET` \| `ACTION.TOUCH_ZOOM_ROTATE` \| `CameraControls.ACTION.TOUCH_ROTATE` \| `CameraControls.ACTION.TOUCH_TRUCK` \| `CameraControls.ACTION.TOUCH_SCREEN_PAN` \| `CameraControls.ACTION.TOUCH_OFFSET` \| `CameraControls.ACTION.NONE` | | |
| - \* is the default. | |
| - The default of `touches.two` and `touches.three` is: | |
| - `TOUCH_DOLLY_TRUCK` for Perspective camera. | |
| - `TOUCH_ZOOM_TRUCK` for Orthographic camera, and can't set `TOUCH_DOLLY_TRUCK` and `TOUCH_DOLLY`. | |
| ## Methods | |
| #### `rotate( azimuthAngle, polarAngle, enableTransition )` | |
| Rotate azimuthal angle(horizontal) and polar angle(vertical). | |
| Every value is added to the current value. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `azimuthAngle` | `number` | Azimuth rotate angle. In radian. | | |
| | `polarAngle` | `number` | Polar rotate angle. In radian. | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| If you want to rotate only one axis, put a angle for the axis to rotate, and `0` for another. | |
| ``` js | |
| rotate( 20 * THREE.MathUtils.DEG2RAD, 0, true ); | |
| ``` | |
| --- | |
| #### `rotateAzimuthTo( azimuthAngle, enableTransition )` | |
| Rotate azimuthal angle(horizontal) to the given angle and keep the same polar angle(vertical) target. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `azimuthAngle` | `number` | Azimuth rotate angle. In radian. | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `rotatePolarTo( polarAngle, enableTransition )` | |
| Rotate polar angle(vertical) to the given angle and keep the same azimuthal angle(horizontal) target. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `polarAngle` | `number` | Polar rotate angle. In radian. | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `rotateTo( azimuthAngle, polarAngle, enableTransition )` | |
| Rotate azimuthal angle(horizontal) and polar angle(vertical) to the given angle. | |
| Camera view will rotate over the orbit pivot absolutely: | |
| Azimuth angle | |
| ``` | |
| 0º | |
| \ | |
| 90º -----+----- -90º | |
| \ | |
| 180º | |
| ``` | |
| 0º front, 90º (`Math.PI / 2`) left, -90º (`- Math.PI / 2`) right, 180º (`Math.PI`) back | |
| ----- | |
| Polar angle | |
| ``` | |
| 180º | |
| | | |
| 90º | |
| | | |
| 0º | |
| ``` | |
| 180º (`Math.PI`) top/sky, 90º (`Math.PI / 2`) horizontal from view, 0º bottom/floor | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `azimuthAngle` | `number` | Azimuth rotate angle to. In radian. | | |
| | `polarAngle` | `number` | Polar rotate angle to. In radian. | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `dolly( distance, enableTransition )` | |
| Dolly in/out camera position. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `distance` | `number` | Distance of dollyIn | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `dollyTo( distance, enableTransition )` | |
| Dolly in/out camera position to given distance. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `distance` | `number` | Distance of dollyIn | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `dollyInFixed( distance, enableTransition )` | |
| Dolly in, but does not change the distance between the target and the camera, and moves the target position instead. | |
| Specify a negative value for dolly out. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `distance` | `number` | Distance of dollyIn | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `zoom( zoomStep, enableTransition )` | |
| Zoom in/out camera. The value is added to camera zoom. | |
| Limits set with `.minZoom` and `.maxZoom` | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `zoomStep` | `number` | zoom scale | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| You can also make zoomIn function using `camera.zoom` property. | |
| e.g. | |
| ``` js | |
| const zoomIn = () => cameraControls.zoom( camera.zoom / 2, true ); | |
| const zoomOut = () => cameraControls.zoom( - camera.zoom / 2, true ); | |
| ``` | |
| --- | |
| #### `zoomTo( zoom, enableTransition )` | |
| Zoom in/out camera to given scale. The value overwrites camera zoom. | |
| Limits set with `.minZoom` and `.maxZoom` | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `zoom` | `number` | zoom scale | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `truck( x, y, enableTransition )` | |
| Truck and pedestal camera using current azimuthal angle. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `x` | `number` | Horizontal translate amount | | |
| | `y` | `number` | Vertical translate amount | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `lookInDirectionOf( x, y, z, enableTransition )` | |
| Look in the given point direction. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `x` | `number` | point x | | |
| | `y` | `number` | point y | | |
| | `z` | `number` | point z | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| #### `setFocalOffset( x, y, z, enableTransition )` | |
| Set focal offset using the screen parallel coordinates. | |
| `z` doesn't affect in Orthographic as with Dolly. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `x` | `number` | Horizontal offset amount | | |
| | `y` | `number` | Vertical offset amount | | |
| | `z` | `number` | Depth offset amount. The result is the same as Dolly but unaffected by `minDistance` and `maxDistance` | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `setOrbitPoint( targetX, targetY, targetZ )` | |
| Set orbit point without moving the camera. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `targetX` | `number` | Orbit center position x | | |
| | `targetY` | `number` | Orbit center position y | | |
| | `targetZ` | `number` | Orbit center position z | | |
| --- | |
| #### `forward( distance, enableTransition )` | |
| Move forward / backward. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `distance` | `number` | Amount to move forward / backward. Negative value to move backward | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `moveTo( x, y, z, enableTransition )` | |
| Move `target` position to given point. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `x` | `number` | x coord to move center position | | |
| | `y` | `number` | y coord to move center position | | |
| | `z` | `number` | z coord to move center position | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `elevate( height, enableTransition )` | |
| Move up / down. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `height` | `number` | Amount to move up / down. Negative value to move down | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `fitToBox( box3OrMesh, enableTransition, { paddingTop, paddingLeft, paddingBottom, paddingRight } )` | |
| Fit the viewport to the box or the bounding box of the object, using the nearest axis. paddings are in unit. | |
| set `cover: true` to fill enter screen. | |
| | Name | Type | Description | | |
| | ----------------------- | ---------------------------- | ----------- | | |
| | `box3OrMesh` | `THREE.Box3` \| `THREE.Mesh` | Axis aligned bounding box to fit the view. | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| | `options` | `object` | Options | | |
| | `options.cover` | `boolean` | Whether fill enter screen or not. Default is `false` | | |
| | `options.paddingTop` | `number` | Padding top. Default is `0` | | |
| | `options.paddingRight` | `number` | Padding right. Default is `0` | | |
| | `options.paddingBottom` | `number` | Padding bottom. Default is `0` | | |
| | `options.paddingLeft` | `number` | Padding left. Default is `0` | | |
| --- | |
| #### `fitToSphere( sphereOrMesh, enableTransition )` | |
| Fit the viewport to the sphere or the bounding sphere of the object. | |
| | Name | Type | Description | | |
| | ------------------ | ------------------------------ | ----------- | | |
| | `sphereOrMesh` | `THREE.Sphere` \| `THREE.Mesh` | bounding sphere to fit the view. | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `setLookAt( positionX, positionY, positionZ, targetX, targetY, targetZ, enableTransition )` | |
| Look at the `target` from the `position`. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `positionX` | `number` | Camera position x. | | |
| | `positionY` | `number` | Camera position y. | | |
| | `positionZ` | `number` | Camera position z. | | |
| | `targetX` | `number` | Orbit center position x. | | |
| | `targetY` | `number` | Orbit center position y. | | |
| | `targetZ` | `number` | Orbit center position z. | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `lerpLookAt( positionAX, positionAY, positionAZ, targetAX, targetAY, targetAZ, positionBX, positionBY, positionBZ, targetBX, targetBY, targetBZ, t, enableTransition )` | |
| Similar to `setLookAt`, but it interpolates between two states. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `positionAX` | `number` | The starting position x of look at from. | | |
| | `positionAY` | `number` | The starting position y of look at from. | | |
| | `positionAZ` | `number` | The starting position z of look at from. | | |
| | `targetAX` | `number` | The starting position x of look at. | | |
| | `targetAY` | `number` | The starting position y of look at. | | |
| | `targetAZ` | `number` | The starting position z of look at. | | |
| | `positionBX` | `number` | Look at from position x to interpolate towards. | | |
| | `positionBY` | `number` | Look at from position y to interpolate towards. | | |
| | `positionBZ` | `number` | Look at from position z to interpolate towards. | | |
| | `targetBX` | `number` | look at position x to interpolate towards. | | |
| | `targetBY` | `number` | look at position y to interpolate towards. | | |
| | `targetBZ` | `number` | look at position z to interpolate towards. | | |
| | `t` | `number` | Interpolation factor in the closed interval. The value must be a number between `0` to `1` inclusive, where `1` is 100% | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `setPosition( positionX, positionY, positionZ, enableTransition )` | |
| Set angle and distance by given position. | |
| An alias of `setLookAt()`, without target change. Thus keep gazing at the current target | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `positionX` | `number` | Position x of look at from. | | |
| | `positionY` | `number` | Position y of look at from. | | |
| | `positionZ` | `number` | Position z of look at from. | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `setTarget( targetX, targetY, targetZ, enableTransition )` | |
| Set the target position where gaze at. | |
| An alias of `setLookAt()`, without position change. Thus keep the same position. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `targetX` | `number` | Position x of look at. | | |
| | `targetY` | `number` | Position y of look at. | | |
| | `targetZ` | `number` | Position z of look at. | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `setBoundary( box3? )` | |
| Set the boundary box that encloses the target of the camera. `box3` is in `THREE.Box3` | |
| | Name | Type | Description | | |
| | ------ | ------------- | ----------- | | |
| | `box3` | `THREE.Box3?` | Boundary area. No argument to remove the boundary. | | |
| --- | |
| #### `setViewport( vector4? )` | |
| Set (or unset) the current viewport. | |
| Set this when you want to use renderer viewport and [`.dollyToCursor`](#properties) feature at the same time. | |
| See: [THREE.WebGLRenderer.setViewport()](https://threejs.org/docs/#api/en/renderers/WebGLRenderer.setViewport) | |
| | Name | Type | Description | | |
| | --------- | ---------------- | ----------- | | |
| | `vector4` | `THREE.Vector4?` | Vector4 that represents the viewport, or `undefined` for unsetting this. | | |
| #### `setViewport( x, y, width, height )` | |
| Same as [`setViewport( vector4 )`](#setviewport-vector4-|-null-), but you can give it four numbers that represents a viewport instead: | |
| | Name | Type | Description | | |
| | -------- | -------- | ----------- | | |
| | `x` | `number` | Leftmost of the viewport. | | |
| | `y` | `number` | Bottommost of the viewport. | | |
| | `width` | `number` | Width of the viewport. | | |
| | `height` | `number` | Height of the viewport. | | |
| --- | |
| #### `getTarget( out, receiveEndValue )` | |
| Returns the orbit center position, where the camera looking at. | |
| | Name | Type | Description | | |
| | ----------------- | --------------- | ----------- | | |
| | `out` | `THREE.Vector3` | The receiving Vector3 instance to copy the result | | |
| | `receiveEndValue` | `boolean` | Whether receive the transition end coords or current. default is `true` | | |
| --- | |
| #### `getPosition( out, receiveEndValue )` | |
| Returns the camera position. | |
| | Name | Type | Description | | |
| | ----------------- | --------------- | ----------- | | |
| | `out` | `THREE.Vector3` | The receiving Vector3 instance to copy the result | | |
| | `receiveEndValue` | `boolean` | Whether receive the transition end coords or current. default is `true` | | |
| --- | |
| #### `getSpherical( out, receiveEndValue )` | |
| Returns the spherical coordinates of the orbit. | |
| | Name | Type | Description | | |
| | ----------------- | --------------- | ----------- | | |
| | `out` | `THREE.Spherical` | The receiving Spherical instance to copy the result | | |
| | `receiveEndValue` | `boolean` | Whether receive the transition end coords or current. default is `true` | | |
| --- | |
| #### `getFocalOffset( out, receiveEndValue )` | |
| Returns the focal offset, which is how much the camera appears to be translated in screen parallel coordinates. | |
| | Name | Type | Description | | |
| | ----------------- | --------------- | ----------- | | |
| | `out` | `THREE.Vector3` | The receiving Vector3 instance to copy the result | | |
| | `receiveEndValue` | `boolean` | Whether receive the transition end coords or current. default is `true` | | |
| --- | |
| #### `stop()` | |
| stop all transitions. | |
| --- | |
| #### `saveState()` | |
| Set current camera position as the default position | |
| --- | |
| #### `normalizeRotations()` | |
| Normalize camera azimuth angle rotation between 0 and 360 degrees. | |
| #### `reset( enableTransition )` | |
| Reset all rotation and position to default. | |
| | Name | Type | Description | | |
| | ------------------ | --------- | ----------- | | |
| | `enableTransition` | `boolean` | Whether to move smoothly or immediately | | |
| --- | |
| #### `update( delta ): boolean` | |
| Update camera position and directions. This should be called in your tick loop and returns `true` if re-rendering is needed. | |
| | Name | Type | Description | | |
| | ------- | -------- | ----------- | | |
| | `delta` | `number` | Delta time between previous update call | | |
| --- | |
| #### `updateCameraUp()` | |
| When you change camera-up vector, run `.updateCameraUp()` to sync. | |
| --- | |
| #### `applyCameraUp()` | |
| Apply current camera-up direction to the camera. | |
| The orbit system will be re-initialized with the current position. | |
| --- | |
| #### `connect()` | |
| Attach all internal event handlers to enable drag control. | |
| --- | |
| #### `disconnect()` | |
| Detach all internal event handlers to disable drag control. | |
| --- | |
| #### `dispose()` | |
| Dispose the cameraControls instance itself, remove all eventListeners. | |
| --- | |
| #### `addEventListener( type: string, listener: function )` | |
| Adds the specified event listener. | |
| --- | |
| #### `removeEventListener( type: string, listener: function )` | |
| Removes the specified event listener. | |
| --- | |
| #### `removeAllEventListeners( type: string )` | |
| Removes all listeners for the specified type. | |
| --- | |
| #### `toJSON()` | |
| Get all state in JSON string | |
| --- | |
| #### `fromJSON( json, enableTransition )` | |
| Reproduce the control state with JSON. `enableTransition` is where anim or not in a boolean. | |
| --- | |
| ## Tips | |
| ### Normalize accumulated azimuth angle: | |
| If you need a normalized accumulated azimuth angle (between 0 and 360 deg), compute with [THREE.MathUtils.euclideanModulo](https://threejs.org/docs/#api/en/math/MathUtils) | |
| e.g.: | |
| ``` js | |
| const TAU = Math.PI * 2; | |
| function normalizeAngle( angle ) { | |
| return THREE.MathUtils.euclideanModulo( angle, TAU ); | |
| } | |
| const normalizedAzimuthAngle = normalizeAngle( cameraControls.azimuthAngle ); | |
| ``` | |
| --- | |
| ### Find the absolute angle to shortest azimuth rotatation: | |
| You may rotate 380deg but actually, you expect to rotate -20deg. | |
| To get the absolute angle, use the below: | |
| ```js | |
| const TAU = Math.PI * 2; | |
| function absoluteAngle( targetAngle, sourceAngle ){ | |
| const angle = targetAngle - sourceAngle | |
| return THREE.MathUtils.euclideanModulo( angle + Math.PI, TAU ) - Math.PI; | |
| } | |
| console.log( absoluteAngle( 380 * THREE.MathUtils.DEG2RAD, 0 ) * THREE.MathUtils.RAD2DEG ); // -20deg | |
| console.log( absoluteAngle( -1000 * THREE.MathUtils.DEG2RAD, 0 ) * THREE.MathUtils.RAD2DEG ); // 80deg | |
| ``` | |
| --- | |
| ### Creating Complex Transitions | |
| All methods that take the `enableTransition` parameter return a `Promise` can be used to create complex animations, for example: | |
| ``` js | |
| async function complexTransition() { | |
| await cameraControls.rotateTo( Math.PI / 2, Math.PI / 4, true ); | |
| await cameraControls.dollyTo( 3, true ); | |
| await cameraControls.fitToSphere( mesh, true ); | |
| } | |
| ``` | |
| This will rotate the camera, then dolly, and finally fit to the bounding sphere of the `mesh`. | |
| The speed and timing of transitions can be tuned using `.restThreshold` and `.smoothTime`. | |
| If `enableTransition` is `false`, the promise will resolve immediately: | |
| ``` js | |
| // will resolve immediately | |
| await cameraControls.dollyTo( 3, false ); | |
| ``` | |
| --- | |
| ## V2 Migration Guide | |
| camera-controls used to use simple damping for its smooth transition. camera-controls v2 now uses [SmoothDamp](https://docs.unity3d.com/ScriptReference/Mathf.SmoothDamp.html). | |
| one of the benefits of using SmoothDamp is, SmoothDamp transition can be controlled with smoothTime which is approximately the time it will take to reach the end position. | |
| Also, the Maximum speed of the transition can be set with `max speed`. | |
| Due to the change, the following are needed. | |
| (if you haven't changed `dampingFactor` and `draggingDampingFactor` in v1.x, nothing is needed) | |
| deprecated | |
| - `dampingFactor` (use smoothTime instead) | |
| - `draggingDampingFactor` (use draggingSmoothTime instead) | |
| added | |
| - `smoothTime` | |
| - `draggingSmoothTime` | |
| - `maxSpeed` | |
| ...That's it! | |
| ## Contributors | |
| This project exists thanks to all the people who contribute. | |
|  | |
| ## Release | |
| Pre-requisites: | |
| 1. a npm registry up and running with a [`NPM_TOKEN`](https://docs.npmjs.com/creating-and-viewing-access-tokens) | |
| ```sh | |
| $ export NPM_TOKEN=npm_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | |
| ``` | |
| 2. a Github [PAT](https://github.com/semantic-release/github#github-authentication) | |
| ```sh | |
| $ export GITHUB_TOKEN=github_pat_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | |
| ``` | |
| ```sh | |
| $ npm run release -- --dry-run | |
| ``` | |