如何调整PlaneGeometry尺寸与相机距离,使其填满屏幕且不越界?
解决方案:Three.js 平面适配屏幕并计算相机距离
核心实现步骤
1. 获取渲染器容器的宽高
直接通过渲染器DOM元素的clientWidth和clientHeight获取当前容器的实际可视尺寸:
const width = renderer.domElement.clientWidth; const height = renderer.domElement.clientHeight;
如果容器包含内边距或边框,可改用offsetWidth/offsetHeight获取包含装饰的整体尺寸。
2. 计算相机到平面的合适距离
基于Three.js透视相机的垂直视场角(FOV)推导距离,确保平面刚好填满屏幕且不超出边界:
- 设相机垂直FOV为
fov(默认57°,即Math.PI/3弧度) - 计算屏幕宽高比:
screenAspect = width / height - 计算平面宽高比:
planeAspect = planeWidth / planeHeight - 根据宽高比匹配情况选择计算逻辑:
- 若屏幕更宽(
screenAspect > planeAspect):以平面宽度为基准,计算让宽度填满屏幕的距离 - 若屏幕更高(
screenAspect <= planeAspect):以平面高度为基准,计算让高度填满屏幕的距离
- 若屏幕更宽(
公式:
- 基于高度的距离:
distance = planeHeight / (2 * Math.tan(fov / 2)) - 基于宽度的距离:
distance = (planeWidth / screenAspect) / (2 * Math.tan(fov / 2))
完整代码示例
// 初始化渲染器 const renderer = new THREE.WebGLRenderer(); document.body.appendChild(renderer.domElement); // 设置平面尺寸(可根据需求调整) const planeWidth = 10; const planeHeight = 5; // 初始化场景 const scene = new THREE.Scene(); // 初始化相机(先设临时位置,后续计算后更新) const fov = 57; // Three.js默认垂直FOV为57° const camera = new THREE.PerspectiveCamera(fov, 1, 0.1, 1000); // 创建平面 const planeGeometry = new THREE.PlaneGeometry(planeWidth, planeHeight); const planeMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true }); const plane = new THREE.Mesh(planeGeometry, planeMaterial); scene.add(plane); // 适配屏幕的核心函数 function fitPlaneToScreen() { // 1. 获取渲染器容器宽高 const width = renderer.domElement.clientWidth; const height = renderer.domElement.clientHeight; // 更新相机宽高比 camera.aspect = width / height; camera.updateProjectionMatrix(); // 2. 计算相机距离 const screenAspect = width / height; const planeAspect = planeWidth / planeHeight; let distance; if (screenAspect > planeAspect) { // 屏幕更宽,以平面宽度为基准计算距离 distance = (planeWidth / screenAspect) / (2 * Math.tan((fov * Math.PI) / 360 / 2)); } else { // 屏幕更高,以平面高度为基准计算距离 distance = planeHeight / (2 * Math.tan((fov * Math.PI) / 360 / 2)); } // 设置相机位置(平面在Z=0,相机沿Z轴放置) camera.position.z = distance; } // 初始化适配 fitPlaneToScreen(); // 窗口 resize 时重新适配 window.addEventListener('resize', () => { fitPlaneToScreen(); renderer.setSize(renderer.domElement.clientWidth, renderer.domElement.clientHeight); }); // 渲染循环 function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate();
预期效果说明
- 平面会根据屏幕宽高比自动匹配,要么宽度填满屏幕,要么高度填满屏幕,不会超出边界
- 窗口尺寸变化时,会自动重新计算相机距离和相机宽高比,保持适配效果
内容的提问来源于stack exchange,提问作者yangpu
相关产品推荐
相关产品推荐

