相机控制

Starter pack

为了在3D场景中定位和动画化相机,我们发现了几种方法来做到这一点:

  • 手动设置相机的位置和旋转。
  • 使用不同类型的控制,例如OrbitControls。

但有时候,我们需要对相机有更多的控制权,这需要大量的代码和计算才能正确完成。幸运的是,有一些库可以帮助我们。

我们将要使用的是camera-controls。这是一个小型库,它允许我们非常轻松地执行各种相机移动和动画。

碰巧的是,Drei为这个库提供了一个包装器,因此我们只需几行代码即可使用它。

入门项目

为了探索这个库的不同功能,我们将创建一个漂亮的3D滑块来展示新的iPhone 15 Pro Max黑色版。

请在iPhone 16发布时联系我,以便我更新本课程 🤭

入门项目包含:

iPhone 15 Pro Max Black

目前我们只能看到iPhone模型

现在,让我们开始玩转相机控制。

控制

为了启用相机控制,我们需要将入门项目中已经存在的 OrbitControls 替换为 Drei 提供的 CameraControls 组件。

我们还将添加对控制的引用,以便我们可以稍后访问并使用其方法。

Experience.jsx:

// ...
import { CameraControls } from "@react-three/drei";
import { useRef } from "react";

export const Experience = () => {
  const controls = useRef();
  return (
    <>
      <CameraControls ref={controls} />
      {/* ... */}
    </>
  );
};

现在可以通过 react-three-fiberuseThree 钩子访问 CameraControls 组件,而不需要引用。更多信息请查阅文档

通过这样做,我们无法注意到与 OrbitControls 的任何主要区别。我们仍然可以旋转平移缩放相机。

API 也有许多共有的控制集,如 distancezoompolarAngleazimuthAngle 等。

CameraControls 组件的亮点在于当我们想要动画化相机时。

我们不会介绍所有可用的控件,但我们会看到最常见的控件。您可以在 camera-controls 文档 中找到完整的列表。

Dolly

dolly 控制允许我们前后移动相机。

让我们使用 Leva 添加按钮来前后移动相机:

// ...
import { button, useControls } from "leva";

export const Experience = () => {
  // ...

  useControls("dolly", {
    in: button(() => {
      controls.current.dolly(1, true);
    }),
    out: button(() => {
      controls.current.dolly(-1, true);
    }),
  });
  // ...
};

dolly 方法的第一个参数是我们想要移动相机的距离。第二个参数是一个布尔值,指示我们是否希望对运动进行动画处理。

我们的相机现在可以前后移动

如果我们想用 OrbitControls 实现同样的效果,我们需要计算相机和目标的新位置。然后我们需要将相机和目标动画化到它们的新位置。

Truck

truck控制允许我们在不改变摄像机方向的情况下,上下左右移动摄像机。

如同我们对dolly控制所做的,让我们添加按钮来实验truck控制:

// ...

export const Experience = () => {
  // ...
  useControls("truck", {
    up: button(() => {
      controls.current.truck(0, -0.5, true);
    }),
    left: button(() => {
      controls.current.truck(-0.5, 0, true);
    }),
    down: button(() => {
      controls.current.truck(0, 0.5, true);
    }),
    right: button(() => {
      controls.current.truck(0.5, 0, true);
    }),
  });
  // ...
};

truck方法的前两个参数是我们希望移动摄像机的horizontalvertical距离。第三个参数是一个布尔值,指示我们是否希望动画化移动。

您可以使用不同的horizontalvertical距离值来对角移动摄像机。

旋转

相机控制提供了一种编程方式来围绕其目标旋转相机,这类似于我们用 OrbitControls 拖动鼠标时的移动。

Orbit rotation schema

让我们添加一些按钮来控制相机围绕其目标旋转:

// ...

export const Experience = () => {
  // ...
  useControls("rotate", {
    up: button(() => {
      controls.current.rotate(0, -0.5, true);
    }),
    down: button(() => {
      controls.current.rotate(0, 0.5, true);
    }),
    left: button(() => {
      controls.current.rotate(-0.5, 0, true);
    }),
    right: button(() => {
      controls.current.rotate(0.5, 0, true);
    }),
  });
  // ...
};

rotate 方法的参数为:

  • azimuthAngle: 水平角度,以弧度表示。
  • polarAngle: 垂直角度,以弧度表示。
  • enableTransition: 一个布尔值,用于指示我们是否希望对该移动进行动画处理。

平滑时间

当我们使用 enableTransition 参数时,可以通过 smoothTime 属性来控制动画时间。

Three.js logoReact logo

React Three Fiber: The Ultimate Guide to 3D Web Development

✨ You have reached the end of the preview ✨

Go to the next level with Three.js and React Three Fiber!

Get full access to this lesson and the complete course when you enroll:

  • 🔓 Full lesson videos with no limits
  • 💻 Access to the final source code
  • 🎓 Course progress tracking & completion
  • 💬 Invite to our private Discord community
Unlock the Full Course – Just $85

One-time payment. Lifetime updates included.