Rotate camera in Three.js with mouse

Javascript3dthree.js

Javascript Problem Overview


I have quite a few objects in my scene so rotating all of them could be a pain. So what is the most easy way to move camera around origin on mouse click and drag? This way all the lights, objects in the scene are in the same location, so the only thing changing is the camera. Three.js does not provide a way to rotate a camera around a point, or does it?

Thank you

Javascript Solutions


Solution 1 - Javascript

Here's a project with a rotating camera. Looking through the source it seems to just move the camera position in a circle.

function onDocumentMouseMove( event ) {

    event.preventDefault();

    if ( isMouseDown ) {

        theta = - ( ( event.clientX - onMouseDownPosition.x ) * 0.5 )
                + onMouseDownTheta;
        phi = ( ( event.clientY - onMouseDownPosition.y ) * 0.5 )
              + onMouseDownPhi;

        phi = Math.min( 180, Math.max( 0, phi ) );

        camera.position.x = radious * Math.sin( theta * Math.PI / 360 )
                            * Math.cos( phi * Math.PI / 360 );
        camera.position.y = radious * Math.sin( phi * Math.PI / 360 );
        camera.position.z = radious * Math.cos( theta * Math.PI / 360 )
                            * Math.cos( phi * Math.PI / 360 );
        camera.updateMatrix();

    }

    mouse3D = projector.unprojectVector(
        new THREE.Vector3(
            ( event.clientX / renderer.domElement.width ) * 2 - 1,
            - ( event.clientY / renderer.domElement.height ) * 2 + 1,
            0.5
        ),
        camera
    );
    ray.direction = mouse3D.subSelf( camera.position ).normalize();

    interact();
    render();

}

Here's another demo and in this one I think it just creates a new THREE.TrackballControls object with the camera as a parameter, which is probably the better way to go.

controls = new THREE.TrackballControls( camera );
controls.target.set( 0, 0, 0 )

Solution 2 - Javascript

take a look at the following examples

http://threejs.org/examples/#misc_controls_orbit

http://threejs.org/examples/#misc_controls_trackball

there are other examples for different mouse controls, but both of these allow the camera to rotate around a point and zoom in and out with the mouse wheel, the main difference is OrbitControls enforces the camera up direction, and TrackballControls allows the camera to rotate upside-down.

All you have to do is include the controls in your html document

<script src="js/OrbitControls.js"></script>

and include this line in your source

controls = new THREE.OrbitControls( camera, renderer.domElement );

Solution 3 - Javascript

Take a look at THREE.PointerLockControls

Solution 4 - Javascript

This might serve as a good starting point for moving/rotating/zooming a camera with mouse/trackpad (in typescript):

class CameraControl {
    zoomMode: boolean = false
    press: boolean = false
    sensitivity: number = 0.02

    constructor(renderer: Three.Renderer, public camera: Three.PerspectiveCamera, updateCallback:() => void){
        renderer.domElement.addEventListener('mousemove', event => {
            if(!this.press){ return }
                
            if(event.button == 0){
                camera.position.y -= event.movementY * this.sensitivity
                camera.position.x -= event.movementX * this.sensitivity        
            } else if(event.button == 2){
                camera.quaternion.y -= event.movementX * this.sensitivity/10
                camera.quaternion.x -= event.movementY * this.sensitivity/10
            }

            updateCallback()
        })    

        renderer.domElement.addEventListener('mousedown', () => { this.press = true })
        renderer.domElement.addEventListener('mouseup', () => { this.press = false })
        renderer.domElement.addEventListener('mouseleave', () => { this.press = false })

        document.addEventListener('keydown', event => {
            if(event.key == 'Shift'){
                this.zoomMode = true
            }
        })

        document.addEventListener('keyup', event => {
            if(event.key == 'Shift'){
                this.zoomMode = false
            }
        })

        renderer.domElement.addEventListener('mousewheel', event => {
            if(this.zoomMode){ 
                camera.fov += event.wheelDelta * this.sensitivity
                camera.updateProjectionMatrix()
            } else {
                camera.position.z += event.wheelDelta * this.sensitivity
            }

            updateCallback()
        })
    }
}

drop it in like:

this.cameraControl = new CameraControl(renderer, camera, () => {
    // you might want to rerender on camera update if you are not rerendering all the time
    window.requestAnimationFrame(() => renderer.render(scene, camera))
})

Controls:

  • move while [holding mouse left / single finger on trackpad] to move camera in x/y plane
  • move [mouse wheel / two fingers on trackpad] to move up/down in z-direction
  • hold shift + [mouse wheel / two fingers on trackpad] to zoom in/out via increasing/decreasing field-of-view
  • move while holding [mouse right / two fingers on trackpad] to rotate the camera (quaternion)

Additionally:

If you want to kinda zoom by changing the 'distance' (along yz) instead of changing field-of-view you can bump up/down camera's position y and z while keeping the ratio of position's y and z unchanged like:

// in mousewheel event listener in zoom mode
const ratio = camera.position.y / camera.position.z
camera.position.y += (event.wheelDelta * this.sensitivity * ratio)
camera.position.z += (event.wheelDelta * this.sensitivity)

Solution 5 - Javascript

OrbitControls and TrackballControls seems to be good for this purpose.

controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;

update in render

controls.update();

Solution 6 - Javascript

Solution 7 - Javascript

Look at simplest example in doc. Here is a source code for this example. It's needed to use THREE.OrbitControls

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionmiki725View Question on Stackoverflow
Solution 1 - JavascriptBurt SampsonView Answer on Stackoverflow
Solution 2 - JavascriptekcrispView Answer on Stackoverflow
Solution 3 - JavascriptPavel GalatonView Answer on Stackoverflow
Solution 4 - JavascriptambientlightView Answer on Stackoverflow
Solution 5 - JavascriptnguyentranView Answer on Stackoverflow
Solution 6 - JavascriptIt's JokerView Answer on Stackoverflow
Solution 7 - JavascriptNikolay PodolnyyView Answer on Stackoverflow