Three.js正交相机下模型跨设备自适应位置(非match media方案)
问题描述
我正试图找到最佳方案,让模型在所有设备上的位置(必要时包含缩放)适配,且无需仅依赖match media。显然我无法使用百分比,因此想了解Three.js是否有内置功能可助我实现理想效果,也欢迎提供其他可行方案。目前我的场景中使用的是正交相机(orthographic camera)。
实际情况
期望效果:
窗口调整大小时模型被裁切:
当前Resize代码
rendererSize.width = window.innerWidth; rendererSize.height = window.innerHeight; aspect = rendererSize.width / rendererSize.height; //* [ORTHOGRAPHIC CAMERA] camera.left = -f * aspect; camera.right = f * aspect; camera.updateProjectionMatrix(); renderer.setSize(rendererSize.width, rendererSize.height);
解决方案
针对正交相机的适配问题,不用依赖matchMedia,可以用以下几种实用方案:
1. 基于模型边界盒动态调整相机参数
这是最精准的方案,先计算模型的包围盒,再根据窗口宽高比调整相机可视范围,确保模型始终完整显示:
// 先计算目标模型的包围盒 const box = new THREE.Box3().setFromObject(yourModel); const size = new THREE.Vector3(); box.getSize(size); const modelWidth = size.x; const modelHeight = size.y; function onWindowResize() { const width = window.innerWidth; const height = window.innerHeight; const aspect = width / height; // 可自定义边距比例,比如1.2就是保留20%的留白 const paddingRatio = 1.2; const targetWidth = modelWidth * paddingRatio; const targetHeight = modelHeight * paddingRatio; // 根据窗口宽高比适配,避免裁切 if (aspect > targetWidth / targetHeight) { // 窗口偏宽,以模型高度为基准计算相机范围 camera.top = targetHeight / 2; camera.bottom = -camera.top; camera.left = -camera.top * aspect; camera.right = camera.top * aspect; } else { // 窗口偏高,以模型宽度为基准计算相机范围 camera.left = -targetWidth / 2; camera.right = targetWidth / 2; camera.top = camera.right / aspect; camera.bottom = -camera.top; } camera.updateProjectionMatrix(); renderer.setSize(width, height); }
2. 固定相机可视比例,动态调整位置
如果不需要精准匹配模型尺寸,也可以固定相机的基础可视范围,再根据窗口比例调整相机位置,保证模型始终在目标区域:
function onWindowResize() { const width = window.innerWidth; const height = window.innerHeight; const aspect = width / height; // 设定基础可视范围大小 const baseRange = 10; if (aspect > 1) { // 宽屏模式:以高度为基准 camera.top = baseRange / 2; camera.bottom = -camera.top; camera.left = -camera.top * aspect; camera.right = camera.top * aspect; } else { // 竖屏模式:以宽度为基准 camera.left = -baseRange / 2; camera.right = baseRange / 2; camera.top = camera.right / aspect; camera.bottom = -camera.top; } // 示例:让模型固定在屏幕右下区域,调整相机位置 camera.position.set(camera.right * 0.8, camera.bottom * 0.8, 10); camera.lookAt(yourModel.position); camera.updateProjectionMatrix(); renderer.setSize(width, height); }
3. 动态调整模型缩放(应急方案)
如果相机参数调整太繁琐,也可以直接根据窗口比例缩放模型,注意保持模型原始比例:
function onWindowResize() { const width = window.innerWidth; const height = window.innerHeight; const aspect = width / height; // 设定模型原始适配的目标宽高比,比如16:9 const targetAspect = 16 / 9; if (aspect > targetAspect) { yourModel.scale.set(1, 1 / aspect * targetAspect, 1); } else { yourModel.scale.set(aspect / targetAspect, 1, 1); } renderer.setSize(width, height); }
关键注意事项
- 你当前代码裁切的核心原因是固定
f值计算相机左右范围,宽高比变化时可视范围无法覆盖模型,必须动态计算参数。 - 调整相机参数后必须调用
camera.updateProjectionMatrix(),否则修改不会生效。 - 若场景有多个模型,计算包围盒时要把所有模型都包含进去(用
box.expandByObject(otherModel))。
内容的提问来源于stack exchange,提问作者aka_lux
相关产品推荐
相关产品推荐

