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

如何调整Orthographic Camera正交相机位置使其居中对准黑色正方形

正交相机居中对准平面异常问题

想要设置Orthographic Camera正交相机的位置,使其居中对准场景中的黑色正方形。目前出现异常问题:相机会自动旋转,仅显示黑色正方形的顶视图,只能看到一条细黑线;偶尔修改代码后页面自动刷新时,才能恢复显示黑色正方形的正确面。
在居中函数中分别尝试了更新相机参数、操作controls两种方案都没有解决问题,相关实现代码如下:

相机居中函数

const centerCamera = (controls, camera) => {
  const point = new THREE.Vector3(0, 500, 1);

  camera.position.copy(point);
  camera.lookAt(point.x, point.y, 10);

  controls.target.copy(point);

  controls.update();

  camera.updateProjectionMatrix();
  camera.updateMatrix();
};

场景实现代码

import "./styles.css";
import * as THREE from "three";
import React from "react";
import { Canvas } from "@react-three/fiber";
import { MapControls, OrthographicCamera } from "@react-three/drei";

const CONTENT_GEOMETRY = roundedRect(-350, -50, 700, 100, 100 / 3.7);

function roundedRect(x = 0, y = 0, width = 50, height = 50, radius = 5) {
  const ctx = new THREE.Shape();
  ctx.moveTo(x, y + radius);
  ctx.lineTo(x, y + height - radius);
  ctx.quadraticCurveTo(x, y + height, x + radius, y + height);
  ctx.lineTo(x + width - radius, y + height);
  ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);
  ctx.lineTo(x + width, y + radius);
  ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
  ctx.lineTo(x + radius, y);
  ctx.quadraticCurveTo(x, y, x, y + radius);
  ctx.closePath();
  return ctx;
}

const centerCamera = (controls, camera) => {
  const point = new THREE.Vector3(0, 500, 1);

  camera.lookAt(point.x, point.y, point.z);

  controls.target.copy(point);

  controls.update();

  camera.updateProjectionMatrix();
  camera.updateMatrix();
};

export default function App() {
  const dpr = typeof window !== "undefined" ? window?.devicePixelRatio ?? 0 : 0;
  return (
    <div className="App">
      <Canvas
        frameloop="always"
        style={{ height: "100vh" }}
        linear
        dpr={Math.max(dpr, 2)}
      >
        <Content
          onMount={(controls, camera) => {
            centerCamera(controls, camera);
          }}
        />
      </Canvas>
    </div>
  );
}

const Content = ({ onMount }) => {
  const controls = React.useRef(null);
  const camera = React.useRef();

  React.useEffect(() => {
    if (controls.current && camera.current) {
      onMount(controls.current, camera.current);
    }
  }, [onMount]);

  return (
    <>
      <MapControls
        ref={controls}
        screenSpacePanning
        dampingFactor={1}
        enableRotate={false}
      />
      <OrthographicCamera ref={camera} makeDefault position={[0, 0, 2]} />
      <mesh position={[0, 500, 1]}>
        <shapeBufferGeometry args={[CONTENT_GEOMETRY]} />
        <meshBasicMaterial color="#000000" />
      </mesh>
    </>
  );
};

解决方案

异常的核心原因是相机和目标平面共面、视线方向参数异常,controls的参数覆写了手动设置的相机属性,按以下方式修改即可:

  1. 相机位置要和目标平面拉开z轴距离,避免共面导致的视口计算异常
  2. 先设置相机朝向,再同步controls参数,避免被controls覆写
  3. 移除不需要的矩阵更新调用,只有修改正交相机的视口/缩放参数时才需要调用updateProjectionMatrix

修改后的居中函数参考:

const centerCamera = (controls, camera) => {
  // 黑色正方形的中心点坐标
  const targetPoint = new THREE.Vector3(0, 500, 1);
  // 相机和平面保持z轴距离,正对着平面
  camera.position.set(targetPoint.x, targetPoint.y, 10);
  // 相机看向平面中心点
  camera.lookAt(targetPoint);
  // 同步controls的观察目标
  controls.target.copy(targetPoint);
  controls.update();
};

如果显示的正方形尺寸不符合预期,可以手动调整OrthographicCamera组件的zoom属性,或者传入left/right/top/bottom参数自定义正交视口大小。

内容的提问来源于stack exchange,提问作者João Sobral

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 23:06:03