在 ThreeJS 中缩放到对象

Posted

技术标签:

【中文标题】在 ThreeJS 中缩放到对象【英文标题】:Zoom to object in ThreeJS 【发布时间】:2014-07-22 13:14:18 【问题描述】:

在three.js中哪里可以改变缩放方向?我想放大鼠标光标的方向,但我不知道在哪里可以更改缩放目标。

【问题讨论】:

【参考方案1】:

我对 Three.js 完全陌生,但它......很棒。我什至不是一个好的开发人员。我正在练习。 我遇到了缩放到鼠标位置的问题,我想我对代码做了一些改进。在这里。

// zooming to the mouse position
window.addEventListener('mousewheel', function (e)  mousewheel(e); , false); 
function mousewheel(event) 
    orbitControl.enableZoom = false;
    event.preventDefault();

    // the following are constants depending on the scale of the scene
    // they need be adjusted according to your model scale  
    var factor = 5; 
    // factor determines how fast the user can zoom-in/out  
    var minTargetToCameraDistanceAllowed = 15; 
    // this is the minimum radius the camera can orbit around a target. 

    // calculate the mouse distance from the center of the window
    var mX = (event.clientX / window.innerWidth) * 2 - 1;
    var mY = -(event.clientY / window.innerHeight) * 2 + 1;
    var vector = new THREE.Vector3(mX, mY, 0.5);

    vector.unproject(camera);
    vector.sub(camera.position);

    if (event.deltaY < 0)  
        // zoom-in -> the camera is approaching the scene
        // with OrbitControls the target is always in front of the camera (in the center of the screen)
        // So when the user zoom-in, the target distance from the camera decrease.
        // This is achieved because the camera position changes, not the target.
        camera.position.addVectors(camera.position, vector.setLength(factor));
     else  
        // zoom-out -> the camera is moving away from the scene -> the target distance increase
        camera.position.subVectors(camera.position, vector.setLength(factor));
    
    // Now camera.position is changed but not the control target. As a result: 
    //  - the distance from the camera to the target is changed, and this is ok.
    //  - the target is no more in the center of the screen and needs to be repositioned. 
    // The new target will be in front of the camera (in the direction of the camera.getWorldDirection() )
    // at a suitable distance (no less than the value of minTargetToCameraDistanceAllowed constant).
    // Thus, the target is pushed a little further if the user approaches too much the target.
    var targetToCameraDistance = Math.max(minTargetToCameraDistanceAllowed, 
                                            orbitControl.target.distanceTo(camera.position));
    var newTarget = camera.getWorldDirection().setLength( targetToCameraDistance ).add(camera.position);
    orbitControl.target = newTarget;

    camera.updateProjectionMatrix();


另一个改进可能是将 targetToCameraDistance 设置为用户开始环绕时鼠标击中的对象的距离。 如果鼠标碰到一个物体,并且距离 > minTargetToCameraDistanceAllowed, 然后计算并设置新目标。 ...但我仍然不知道该怎么做。

【讨论】:

【参考方案2】:

如果您使用的是轨迹球控件,请设置

trackBallControls.noZoom=true;

在鼠标滚轮事件中使用此代码,

mousewheel = function (event) 

            event.preventDefault();
            var factor = 15;
            var mX = (event.clientX / jQuery(container).width()) * 2 - 1;
            var mY = -(event.clientY / jQuery(container).height()) * 2 + 1;
            var vector = new THREE.Vector3(mX, mY, 0.1);

            vector.unproject(Camera);
            vector.sub(Camera.position);
            if (event.deltaY < 0) 
                Camera.position.addVectors(Camera.position, vector.setLength(factor));
                trackBallControls.target.addVectors(trackBallControls.target, vector.setLength(factor));
                Camera.updateProjectionMatrix();
             else 
                Camera.position.subVectors(Camera.position, vector.setLength(factor));
                trackBallControls.target.subVectors(trackBallControls.target, vector.setLength(factor));

            

        ;

【讨论】:

【参考方案3】:

更新了 wetwipe 的解决方案以支持 Three.js 的第 71 版,并对其进行了一些清理,就像一个魅力,请参阅 http://www.tectractys.com/market_globe.html 以获取完整的使用示例:

mX = ( event.clientX / window.innerWidth ) * 2 - 1;
mY = - ( event.clientY / window.innerHeight ) * 2 + 1;
var vector = new THREE.Vector3(mX, mY, 1 );
vector.unproject(camera);
vector.sub(camera.position);
camera.position.addVectors(camera.position,vector.setLength(factor));
controls.target.addVectors(controls.target,vector.setLength(factor));

【讨论】:

什么是控件实例?【参考方案4】:

所以我最近遇到了类似的问题,但我需要缩放才能应用到更广阔的空间。我在他的解决方案中采用了Niekes 提供的代码,并提出了以下内容:

container.on('mousewheel', function ( ev )

        var factor = 10;

        var WIDTH = window.innerWidth;
        var HEIGHT = window.innerHeight;

        var mX = ( ev.clientX / WIDTH ) * 2 - 1;
        var mY = - ( ev.clientY / HEIGHT ) * 2 + 1;

        var vector = new THREE.Vector3(mX, mY, 1 );
        projector.unprojectVector( vector, camera );
        vector.sub( camera.position ).normalize();

        if( ev.originalEvent.deltaY < 0 )
            camera.position.x += vector.x * factor;
            camera.position.y += vector.y * factor;
            camera.position.z += vector.z * factor;
            controls.target.x += vector.x * factor;
            controls.target.y += vector.y * factor;
            controls.target.z += vector.z * factor;
         else
            camera.position.x -= vector.x * factor;
            camera.position.y -= vector.y * factor;
            camera.position.z -= vector.z * factor;
            controls.target.x -= vector.x * factor;
            controls.target.y -= vector.y * factor;
            controls.target.z -= vector.z * factor;
        
);

它不漂亮,但至少是实用的。欢迎改进:)

【讨论】:

它不适用于正交相机。您有任何关于正交相机的工作吗? @Aashajoney:我已经有一段时间没有研究过three.js了。也许这有帮助?:***.com/a/41583081/2299557 感谢您的回复。但该链接用于将对象拟合到场景中。 很公平......我看到这实际上是我之前链接到的你的帖子。所以我找到了this,这似乎是有道理的。不过,忽略这一点,我还找到了一个示例here,它从源头上似乎可以让您大部分时间到达那里。剩下的就是移动相机/场景以使目标对象居中。应该是鼠标下物体的一些坐标、相机位置/中心和场景位置/中心的组合。可能是错的,但那是我的几分钱...... 欢迎您的回复【参考方案5】:

好的!我解决了这样的问题...只需禁用 THREEJS 提供的缩放功能。

controls.noZoom = true;

$('body').on('mousewheel', function (e)

        var mouseX = (e.clientX - (WIDTH/2)) * 10;
        var mouseY = (e.clientY - (HEIGHT/2)) * 10;

        if(e.originalEvent.deltaY < 0) // zoom to the front
            camera.position.x -= mouseX * .00125;
            camera.position.y += mouseY * .00125;
            camera.position.z += 1.1 * 10;
            controls.target.x -= mouseX * .00125;
            controls.target.y += mouseY * .00125;
            controls.target.z += 1.1 * 10;
        else                          // zoom to the back
            camera.position.x += mouseX * .00125;
            camera.position.y -= mouseY * .00125;
            camera.position.z -= 1.1 * 10;
            controls.target.x += mouseX * .00125;
            controls.target.y -= mouseY * .00125;
            controls.target.z -= 1.1 * 10;
        
);

我知道它并不完美......但我希望它会对你有所帮助......无论如何......我会努力让它变得更好。

【讨论】:

它不适用于正交相机。我们需要遵循不同的方法吗?【参考方案6】:

从未听说过缩放方向,

您可能想要检查相机的 FOV 参数,

以及调用它来应用更改:

yourCam.updateProjectionMatrix();

【讨论】:

好吧,我的意思是我想要像谷歌地图中那样的缩放行为......鼠标光标是兴趣点,当你缩放时,相机会沿着鼠标光标的方向移动。 ..现在您可以缩放到文档的中心...有什么想法吗? 嗯...有点,这不是微不足道的。您必须修改投影矩阵。如果你看opengl矩阵,你需要修改左右上下的字段。所以你必须找到你的新中心,倾斜投影,然后缩放它(基本上和改变 fov 一样)。

以上是关于在 ThreeJS 中缩放到对象的主要内容,如果未能解决你的问题,请参考以下文章

转 threejs中3D视野的缩放实现

threeJS 导入模型(不确定尺寸)后如何确定相机位置及物体缩放比例

ThreeJS中一组3D对象的中心轴

如何在threejs中通过raycaster从相交检查中排除辅助对象?

如何使用 Threejs 更改对象的 zOrder?

使用ThreeJS制作门户