Rotate camera in Three.js with mouse

前端 未结 5 1710
心在旅途
心在旅途 2020-12-04 07:09

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 a

相关标签:
5条回答
  • 2020-12-04 07:33

    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)
    
    0 讨论(0)
  • 2020-12-04 07:37

    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();
    
    0 讨论(0)
  • 2020-12-04 07:42

    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 )
    
    0 讨论(0)
  • 2020-12-04 07:49

    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 );
    
    0 讨论(0)
  • 2020-12-04 07:56

    Take a look at THREE.PointerLockControls

    0 讨论(0)
提交回复
热议问题