【问题标题】:How to recreate the Three.js OrbitControl movement on mouse move?如何在鼠标移动时重新创建 Three.js OrbitControl 移动?
【发布时间】:2016-09-06 20:14:55
【问题描述】:

我想重新创建 Three.js OrbitControl 移动而不需要单击和拖动,即简单地使相机跟随鼠标移动。

我尝试从头开始重新创建它,但它太费力了,因为问题是相机在三个轴上移动,而不仅仅是两个轴。我很确定有些人以前做过。

具体来说,我希望相机在场景原点周围移动,与它保持相同的距离。

【问题讨论】:

  • 为了解决这个问题,您必须了解OrbitControls 的工作原理:它使用目标和相机,本质上是一个向量。 OrbitControls 的输入在此向量“相机 -> 目标”上进行计算。例如。旋转将采用该向量的当前角度(相对于某个轴),将该角度修改为所需的量,然后将相机移动到向量的新端点并将其朝向目标旋转。向量的长度保持不变,您到目标的距离也是如此。
  • 我明白你的意思,但我如何告诉 OrbitControls 新位置?我一直在查看script,但没有看到输入新向量的方法。我已经看到它确实删除了 mousemove 事件here。我应该 hack/fork 这个脚本来制作一个新版本吗?
  • 您必须进行一些更改才能使其执行您想要的操作,例如删除点击检测,使 mousemove 和 touchmove 事件始终处于活动状态。另请查看rotateLeftrotateUp 方法(它们也处理Right 和Down),这些已经用于更改handleMouseMoveRotate 中矢量的角度。

标签: javascript three.js perspectivecamera


【解决方案1】:

我和 OP 有同样的要求。在Leeft's cmets 的帮助下,我就是这样解决的:

  1. 更新 OrbitControls.js 以将函数 handleMouseMoveRotate 的范围从

    function handleMouseMoveRotate( event )
    

    this.handleMouseMoveRotate = function ( event )
    

    这是您在自己的代码中手动使用此方法所必需的。

  2. 在加载模型的 JS 代码中,使用 dispose 方法删除默认鼠标控件并为手动调用 handleMouseMoveRotatemousemove 添加自己的事件处理程序:

    init();
    animate();
    
    function init() {
        // Set up Camera, Scene and OrbitControls
        camera = new THREE.PerspectiveCamera( 45, containerWidth / containerHeight );
        scene = new THREE.Scene();
        controls = new THREE.OrbitControls(camera);
    
        // Remove default OrbitControls event listeners
        controls.dispose();
        controls.update();
    
        ... // omitted for brevity: Load model and Renderer
    
        document.addEventListener('mousemove', onDocumentMouseMove, false);
    }
    
    function onDocumentMouseMove( event ) {
        // Manually fire the event in OrbitControls
        controls.handleMouseMoveRotate(event);
    }
    
    function animate() {
        requestAnimationFrame( animate );
        render();
    }
    
    function render() {
        controls.update();
        camera.lookAt( scene.position );
        renderer.render( scene, camera );
    }
    

注意:此解决方案会删除所有库侦听器。如果您有兴趣,可以再次启用它们,将它们从here 复制到update method 的末尾。

【讨论】:

  • 感谢您努力寻找解决方案。我还没有测试它,但是我已经看到dispose()will remove every event listener set by the library 并且update() 方法不会将它们设置回they are called outside that method。这个猴子补丁是否会移除 OrbitControl 功能(例如缩放滚动)?
  • dispose() 确实删除了原生 OrbitControl 功能(例如缩放和滚动)。 update() 方法运行时不会重新添加它们,这意味着您可以创建自己的事件处理程序方法 - 在这种情况下,调用我们感兴趣的唯一鼠标控件 - handleMouseMoveRotate
  • 意识到这一点很重要。如果你没问题,我会更新答案。
  • 这似乎抛出 Maximum call stack size exceeded 错误
猜你喜欢
  • 2018-06-09
  • 2022-01-09
  • 1970-01-01
  • 2014-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多