【问题标题】:ThreeJS. How to implement ZoomALL and make sure a given box fills the canvas area?三JS。如何实现 ZoomALL 并确保给定的框填充画布区域?
【发布时间】:2026-01-14 08:10:01
【问题描述】:

我正在寻找一种功能,以确保给定的框或球体在 WebGL 画布中可见,并且适合画布区域。 我正在使用透视相机,相机已经指向物体的中间。 我知道这可以通过改变 FOV 角度或沿视轴移动相机来实现。

知道如何使用 ThreeJS 实现这一点吗?

【问题讨论】:

  • 这个问题之前已经回答过:herehere
  • 您提供的链接解释了如何计算缩放系数。在我的情况下,我还想聚焦相机以使给定的框可见,而不改变相机方向。

标签: camera three.js webgl


【解决方案1】:

这就是我最终实现它的方式:

var camera = new THREE.PerspectiveCamera(35,1,1, 100000);
var controls = new THREE.TrackballControls( me.camera , container);
[...]


/**
 * point the current camera to the center
 * of the graphical object (zoom factor is not affected)
 *
 * the camera is moved in its  x,z plane so that the orientation 
 * is not affected either
 */
function pointCameraTo (node) {

    var me = this;

    // Refocus camera to the center of the new object
    var COG = shapeCenterOfGravity(node);

    var v = new THREE.Vector3();
    v.subVectors(COG,me.controls.target);

    camera.position.addVectors(camera.position,v);

    // retrieve camera orientation and pass it to trackball  
    camera.lookAt(COG);
    controls.target.set( COG.x,COG.y,COG.z );  

};

/**
 *  Zoom to object
 */
function zoomObject (node) {

   var me = this; 

   var bbox = boundingBox(node);
   if (bbox.empty()) {
       return;
   }
   var COG =  bbox.center();

   pointCameraTo(node);

   var sphereSize = bbox.size().length() * 0.5;
   var distToCenter = sphereSize/Math.sin( Math.PI / 180.0 * me.camera.fov * 0.5);

   // move the camera backward 

   var target = controls.target;
   var vec = new THREE.Vector3();
   vec.subVectors( camera.position, target );
   vec.setLength( distToCenter );
   camera.position.addVectors(  vec , target );
   camera.updateProjectionMatrix();
   render3D();
};

这方面的一个例子可以在https://github.com/OpenWebCAD/node-occ-geomview/blob/master/client/geom_view.js中看到

【讨论】:

    【解决方案2】:

    我是这样做的{使用 TrackBall 放大/缩小平移等}

    function init(){
    ......
    ......
    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;
    
    controls.keys = [65, 83, 68];
    
    controls.addEventListener('change', render);
    
    .....
    .....
    render(scene, camera);
    animate();
    }
    function render() 
    
    {
        renderer.render(scene, camera);
        //stats.update();
    }
    
    function animate() {
        requestAnimationFrame(animate);
        controls.update();
    }
    

    【讨论】: