Nice Parakeet Marriage

    camera-controls
    TypeScript icon, indicating that this package has built-in type declarations

    1.34.4 • Public • Published

    camera-controls

    A camera control for three.js, similar to THREE.OrbitControls yet supports smooth transitions and more features.

    Latest NPM release

    documentation

    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

    Usage

    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:

    CameraControls.install( { THREE: THREE } );

    You can then proceed to use CameraControls.

    Note: If you do not wish to use enter three.js to reduce file size(tree-shaking for example), make a subset to install.

    import {
    	MOUSE,
    	Vector2,
    	Vector3,
    	Vector4,
    	Quaternion,
    	Matrix4,
    	Spherical,
    	Box3,
    	Sphere,
    	Raycaster,
    	MathUtils,
    } from 'three';
    
    const subsetOfTHREE = {
    	MOUSE     : MOUSE,
    	Vector2   : Vector2,
    	Vector3   : Vector3,
    	Vector4   : Vector4,
    	Quaternion: Quaternion,
    	Matrix4   : Matrix4,
    	Spherical : Spherical,
    	Box3      : Box3,
    	Sphere    : Sphere,
    	Raycaster : Raycaster,
    	MathUtils : {
    		DEG2RAD: MathUtils.DEG2RAD,
    		clamp: MathUtils.clamp,
    	},
    };
    
    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.

    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

    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 0 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.
    .dampingFactor number 0.05 The damping inertia. The value must be between Math.EPSILON to 1 inclusive. Setting 1 to disable smooth transitions.
    .draggingDampingFactor number 0.25 The damping inertia while dragging. The value must be between Math.EPSILON to 1 inclusive. Setting 1 to disable smooth transitions.
    .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.
    .verticalDragToForward boolean false The same as .screenSpacePanning in three.js's OrbitControls.
    .dollyToCursor boolean false true to enable Dolly-in to the mouse cursor coords.
    .colliderMeshes array [] An array of Meshes to collide with camera ².
    .infinityDolly boolean false true to enable Infinity Dolly ³.
    .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?
    2. Be aware colliderMeshes may decrease performance. The collision test uses 4 raycasters from the camera since the near plane has 4 corners.
    3. When the Dolly distance is less than the minDistance, radius of the sphere will be set minDistance automatically.

    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.

    User input config

    Working example: user input config

    button to assign behavior
    mouseButtons.left CameraControls.ACTION.ROTATE* | CameraControls.ACTION.TRUCK | CameraControls.ACTION.OFFSET | CameraControls.ACTION.DOLLY | CameraControls.ACTION.ZOOM | CameraControls.ACTION.NONE
    mouseButtons.right CameraControls.ACTION.ROTATE | CameraControls.ACTION.TRUCK* | CameraControls.ACTION.OFFSET | CameraControls.ACTION.DOLLY | CameraControls.ACTION.ZOOM | CameraControls.ACTION.NONE
    mouseButtons.shiftLeft CameraControls.ACTION.ROTATE | CameraControls.ACTION.TRUCK | CameraControls.ACTION.OFFSET | CameraControls.ACTION.DOLLY | CameraControls.ACTION.ZOOM | CameraControls.ACTION.NONE*
    mouseButtons.wheel ¹ CameraControls.ACTION.ROTATE | CameraControls.ACTION.TRUCK | CameraControls.ACTION.OFFSET | CameraControls.ACTION.DOLLY | CameraControls.ACTION.ZOOM | CameraControls.ACTION.NONE
    mouseButtons.middle ² CameraControls.ACTION.ROTATE | CameraControls.ACTION.TRUCK | 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_OFFSET | CameraControls.ACTION.DOLLY
    touches.two ACTION.TOUCH_DOLLY_TRUCK | ACTION.TOUCH_DOLLY_OFFSET | ACTION.TOUCH_ZOOM_TRUCK | ACTION.TOUCH_ZOOM_OFFSET | ACTION.TOUCH_DOLLY | ACTION.TOUCH_ZOOM | CameraControls.ACTION.TOUCH_ROTATE | CameraControls.ACTION.TOUCH_TRUCK | CameraControls.ACTION.TOUCH_OFFSET | CameraControls.ACTION.NONE
    touches.three ACTION.TOUCH_DOLLY_TRUCK | ACTION.TOUCH_DOLLY_OFFSET | ACTION.TOUCH_ZOOM_TRUCK | ACTION.TOUCH_ZOOM_OFFSET | CameraControls.ACTION.TOUCH_ROTATE | CameraControls.ACTION.TOUCH_TRUCK | 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.

    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

    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.

    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

    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

    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.

    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.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 )

    Make an orbit with given points.

    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 )

    setLookAt without target, 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 )

    setLookAt without position, Stay still at the 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 feature at the same time.

    See: THREE.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 ), 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.

    getPosition( out )

    Returns its current position.

    Name Type Description
    out THREE.Vector3 The receiving vector

    getTarget( out )

    Returns its current gazing target, which is the center position of the orbit.

    Name Type Description
    out THREE.Vector3 The receiving vector

    getFocalOffset( out )

    Returns its current focal offset, which is how much the camera appears to be translated in screen parallel coordinates.

    Name Type Description
    out THREE.Vector3 The receiving vector

    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.


    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.


    dispose()

    Dispose the cameraControls instance itself, remove all eventListeners.


    Tips

    Normalize accumulated azimuth angle:

    If you need a normalized accumulated azimuth angle (between 0 and 360 deg), compute with THREE.MathUtils.euclideanModulo e.g.:

    const normalizedAzimuthAngle = THREE.MathUtils.euclideanModulo( cameraControls.azimuthAngle, 360 * THREE.MathUtils.DEG2RAD );

    Creating Complex Transitions

    All methods that take the enableTransition parameter return a Promise can be used to create complex animations, for example:

    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 .dampingFactor.

    If enableTransition is false, the promise will resolve immediately:

    // will resolve immediately
    await cameraControls.dollyTo( 3, false );

    Breaking changes

    @1.16.0 dolly() will take opposite value. e.g. dolly-in to dolly( 1 ) (used be dolly-in to dolly( -1 ))

    Contributors

    This project exists thanks to all the people who contribute.

    Install

    npm i camera-controls

    DownloadsWeekly Downloads

    10,790

    Version

    1.34.4

    License

    MIT

    Unpacked Size

    386 kB

    Total Files

    31

    Last publish

    Collaborators

    • yomotsu
    • fms-cat