Javascript 用鼠标在 Three.js 中旋转相机

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8426822/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 05:58:12  来源:igfitidea点击:

Rotate camera in Three.js with mouse

javascript3dthree.js

提问by miki725

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?

我的场景中有很多对象,因此旋转所有对象可能会很痛苦。那么在鼠标单击和拖动时围绕原点移动相机的最简单方法是什么?这样场景中的所有灯光、物体都在同一个位置,所以唯一改变的是相机。Three.js 没有提供围绕一个点旋转相机的方法,或者是吗?

Thank you

谢谢

回答by Burt Sampson

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 demoand in this one I think it just creates a new THREE.TrackballControlsobject with the camera as a parameter, which is probably the better way to go.

这是另一个演示,在这个演示中,我认为它只是THREE.TrackballControls用相机作为参数创建了一个新对象,这可能是更好的方法。

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

回答by ekcrisp

take a look at the following examples

看看下面的例子

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

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

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

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.

还有其他不同鼠标控件的示例,但这两种控件都允许相机围绕一个点旋转并使用鼠标滚轮放大和缩小,主要区别在于 OrbitControls 强制相机向上方向,而 TrackballControls 允许相机向上旋转-下。

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

您所要做的就是在 html 文档中包含控件

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

and include this line in your source

并将此行包含在您的源中

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

回答by ambientlight

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)
  • 移动[按住鼠标左键/单指在触控板上]在 x/y 平面移动相机
  • 移动[鼠标滚轮/触控板上的两个手指]在 z 方向上/下移动
  • 按住 shift + [鼠标滚轮/触控板上的两根手指]通过增加/减少视野来放大/缩小
  • 移动,同时[关于触控板鼠标右/两个手指]保持旋转相机(四元)

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:

如果您想通过更改“距离”(沿 yz)而不是更改视野来进行缩放,您可以上下颠簸相机的位置 y 和 z,同时保持位置的 y 和 z 的比率不变,例如:

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

回答by Pavel Galaton

Take a look at THREE.PointerLockControls

看一下 THREE.PointerLockControls

回答by nguyentran

OrbitControls and TrackballControls seems to be good for this purpose.

OrbitControls 和 TrackballControls 似乎很适合这个目的。

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();