使用 Three.js 创建一个场景(Creating a Scene)

person 少陵野老    watch_later 2024-10-09 22:08:13
visibility 41    class Three.js    bookmark 专栏

Three.js 是一个功能强大的 JavaScript 库,专门用于在网页中创建和展示 3D 图形。创建一个 3D 场景是使用 Three.js 的基本任务之一。在本篇博客中,我们将详细探讨如何使用 Three.js 创建一个场景,涵盖场景的基本元素、属性、方法,以及如何与其他组件结合使用。

1. 场景的基本构成

在 Three.js 中,一个基本的 3D 场景通常包括以下几个主要组成部分:

  • 场景(Scene):用于容纳所有的 3D 对象、光源和摄像机。
  • 摄像机(Camera):视图的“眼睛”,负责观察场景。
  • 渲染器(Renderer):将场景和摄像机渲染成图像并显示在网页上。
  • 几何体(Geometry):定义 3D 形状的基础。
  • 材质(Material):给几何体上色和添加纹理。
  • 光源(Light):照亮场景中的物体。

2. 创建场景的步骤

下面我们将逐步创建一个基本的 3D 场景,包含一个旋转的立方体、一个平面作为地面,以及一个光源。

2.1 安装和引入 Three.js

首先,我们需要在 HTML 文件中引入 Three.js。你可以选择通过 npm 安装或者直接引入 CDN。以下是通过 CDN 引入的示例:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three.js 创建场景示例</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>

2.2 初始化场景

<script> 标签中,我们可以开始创建场景、摄像机和渲染器。

// 创建场景
const scene = new THREE.Scene();

// 创建摄像机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;

// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

2.3 添加几何体

接下来,我们将添加一个立方体和一个平面:

// 创建立方体
const geometry = new THREE.BoxGeometry();  // 立方体几何体
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });  // 绿色材质
const cube = new THREE.Mesh(geometry, material);  // 创建立方体网格
scene.add(cube);  // 将立方体添加到场景中

// 创建平面
const planeGeometry = new THREE.PlaneGeometry(5, 5);  // 平面几何体
const planeMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff, side: THREE.DoubleSide });  // 白色材质
const plane = new THREE.Mesh(planeGeometry, planeMaterial);  // 创建平面网格
plane.rotation.x = -Math.PI / 2;  // 将平面旋转以适应地面
scene.add(plane);  // 将平面添加到场景中

2.4 添加光源

为了让场景更生动,我们可以添加光源:

// 创建光源
const ambientLight = new THREE.AmbientLight(0x404040);  // 环境光
scene.add(ambientLight);  // 将环境光添加到场景中

const directionalLight = new THREE.DirectionalLight(0xffffff, 1);  // 平行光
directionalLight.position.set(5, 5, 5);  // 设置光源位置
scene.add(directionalLight);  // 将平行光添加到场景中

2.5 动画循环

接下来,我们需要实现一个动画循环,使得立方体能够旋转并不断渲染场景:

// 动画函数
function animate() {
    requestAnimationFrame(animate);  // 请求下一帧
    cube.rotation.x += 0.01;  // 旋转立方体
    cube.rotation.y += 0.01;  // 旋转立方体
    renderer.render(scene, camera);  // 渲染场景
}

// 启动动画
animate();

2.6 处理窗口大小变化

为了确保在窗口大小改变时场景能正常显示,我们可以添加事件监听器:

// 处理窗口大小变化
window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;  // 更新摄像机宽高比
    camera.updateProjectionMatrix();  // 更新投影矩阵
    renderer.setSize(window.innerWidth, window.innerHeight);  // 更新渲染器大小
});

3. 完整代码示例

将上述代码整合起来,完整的 HTML 文件如下:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three.js 创建场景示例</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>
    <script>
        // 创建场景
        const scene = new THREE.Scene();

        // 创建摄像机
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.z = 5;

        // 创建渲染器
        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        // 创建立方体
        const geometry = new THREE.BoxGeometry();
        const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
        const cube = new THREE.Mesh(geometry, material);
        scene.add(cube);

        // 创建平面
        const planeGeometry = new THREE.PlaneGeometry(5, 5);
        const planeMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff, side: THREE.DoubleSide });
        const plane = new THREE.Mesh(planeGeometry, planeMaterial);
        plane.rotation.x = -Math.PI / 2;
        scene.add(plane);

        // 创建光源
        const ambientLight = new THREE.AmbientLight(0x404040);
        scene.add(ambientLight);

        const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
        directionalLight.position.set(5, 5, 5);
        scene.add(directionalLight);

        // 动画函数
        function animate() {
            requestAnimationFrame(animate);
            cube.rotation.x += 0.01;
            cube.rotation.y += 0.01;
            renderer.render(scene, camera);
        }

        // 启动动画
        animate();

        // 处理窗口大小变化
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });
    </script>
</body>
</html>

4. 进一步扩展

在上面的示例中,我们创建了一个基本的 3D 场景,但这只是三维编程的起点。Three.js 提供了许多其他功能,可以使你的场景更加丰富和交互。

4.1 添加更多几何体

你可以创建更多不同的几何体,例如球体、圆柱体等:

// 创建球体
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.x = 3;  // 设置球体位置
scene.add(sphere);  // 将球体添加到场景中

4.2 使用纹理

你可以为几何体添加纹理,以增强视觉效果:

// 加载纹理
const textureLoader = new THREE.TextureLoader();
const texturedMaterial = new THREE.MeshBasicMaterial({ map: textureLoader.load('path/to/texture.jpg') });
const texturedCube = new THREE.Mesh(geometry, texturedMaterial);
scene.add(texturedCube);

4.3 实现交互

你可以使用鼠标和键盘事件来实现与场景的交互,例如缩放、旋转等。

// 监听鼠标移动事件
window.addEventListener('mousemove', (event) => {
    cube.rotation.x = event.clientY / window.innerHeight * Math.PI;
    cube.rotation.y = event.clientX / window.innerWidth * Math.PI;
});

5. 结论

通过以上步骤,你应该能够使用 Three.js 创建一个基本的 3D 场景并逐步扩展。Three.js 提供了强大的功能,让你可以深入探索 3D 图形的世界。希望这篇博客能为你在 Three.js 的学习旅程中提供帮助。如果你有任何问题,欢迎在评论区留言讨论!

评论区
评论列表
menu