You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Three.js场景保持camera.position.y视角并在canvas居中?

解决Three.js相机Y轴偏移后场景居中且无倾斜的问题

核心需求拆解

你需要的是:

  • 相机position.y设为任意值时,物体保持正面朝向相机(无倾斜)(和示例2效果一致)
  • 物体在canvas中垂直、水平完全居中(解决示例2场景偏下的问题)

问题根源

示例2中相机保持默认朝向(沿-z轴),物体正面朝向相机所以无倾斜,但相机在y=7位置时,物体(原点)处于相机视锥体的下方区域,因此在屏幕中偏下。示例1调用lookAt(0,0,0)导致相机倾斜,物体正面不再朝向相机,出现倾斜效果。

实现方案

保持相机默认朝向(沿-z轴,确保物体无倾斜),通过调整投影矩阵偏移视锥体,让物体回到屏幕中央。以下是两种可行方法:

方法1:使用setViewOffset快速偏移

利用Three.js相机的setViewOffset方法,计算视锥体需要向上偏移的像素量,将物体拉回屏幕中央:

// 初始化相机
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 7, 5); // 保持z轴默认距离,不调用lookAt

// 计算并更新相机偏移
function updateCameraOffset() {
  const canvasWidth = window.innerWidth;
  const canvasHeight = window.innerHeight;
  const zDist = camera.position.z; // 相机到物体(原点)的z轴距离
  const halfHeight = Math.tan(THREE.MathUtils.degToRad(camera.fov / 2)) * zDist;
  const yOffsetWorld = camera.position.y; // 相机与物体的y轴偏移量
  const offsetRatio = yOffsetWorld / halfHeight;
  const offsetY = offsetRatio * (canvasHeight / 2);

  // 向上偏移视锥体,抵消y轴位置差
  camera.setViewOffset(canvasWidth, canvasHeight, 0, -offsetY, canvasWidth, canvasHeight);
  camera.aspect = canvasWidth / canvasHeight;
  camera.updateProjectionMatrix();
}

// 初始化及窗口resize时调用
updateCameraOffset();
window.addEventListener('resize', () => {
  updateCameraOffset();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

方法2:手动修改投影矩阵(更精准)

直接构建透视投影矩阵,调整视锥体的上下边界,让物体处于视锥体中心:

// 初始化相机
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 7, 5);

// 更新投影矩阵
function updateCameraProjection() {
  const n = camera.near;
  const f = camera.far;
  const fov = camera.fov;
  const aspect = camera.aspect;
  const zDist = camera.position.z;
  const yOffsetWorld = camera.position.y;

  const tanFovHalf = Math.tan(THREE.MathUtils.degToRad(fov / 2));
  // 调整视锥体上下边界,抵消y轴偏移
  const t = n * tanFovHalf - (n * yOffsetWorld) / zDist;
  const b = -n * tanFovHalf - (n * yOffsetWorld) / zDist;
  const l = -aspect * n * tanFovHalf;
  const r = aspect * n * tanFovHalf;

  camera.projectionMatrix.makePerspective(l, r, b, t, n, f);
}

// 初始化及窗口resize时调用
updateCameraProjection();
window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  updateCameraProjection();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

适配任意camera.position.y值

无论你将camera.position.y设为多少,只需在修改后调用对应的更新函数(updateCameraOffset或updateCameraProjection),即可自动重新计算偏移,保持场景居中且无倾斜。


内容的提问来源于stack exchange,提问作者Sanjeet M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 08:05:25