news 2026/7/15 20:40:00

Three.js专栏(二)、从零构建:环境配置与首个3D场景实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Three.js专栏(二)、从零构建:环境配置与首个3D场景实战

1. 环境准备:从零搭建Three.js开发环境

第一次接触Three.js时,最让人头疼的就是环境配置。我刚开始学习时,花了大半天时间才把开发环境跑起来。现在回想起来,其实只需要几个简单步骤就能搞定。

1.1 安装Node.js和npm

Three.js的开发离不开Node.js环境。如果你还没安装,可以去Node.js官网下载LTS版本。安装完成后,打开终端输入以下命令检查是否安装成功:

node -v npm -v

我建议使用nvm来管理Node.js版本,这样可以在不同项目间切换版本。特别是在团队协作时,能避免"在我机器上能跑"的问题。

1.2 创建项目目录

找个你喜欢的位置,新建一个项目文件夹。我习惯用VSCode开发,所以直接右键在终端打开:

mkdir threejs-starter cd threejs-starter npm init -y

这个命令会生成package.json文件,记录项目依赖和配置。接下来我们要安装Three.js核心库。

1.3 安装Three.js

现在安装Three.js非常简单,只需要一行命令:

npm install three --save

安装完成后,你会在node_modules文件夹下找到three模块。我建议同时安装几个常用辅助工具:

npm install dat.gui stats.js --save-dev

dat.gui可以创建可视化控制面板,stats.js能显示性能指标,对调试很有帮助。

2. 开发服务器配置

2.1 选择开发服务器

Three.js项目需要运行在服务器环境下。我测试过几种方案:

  1. live-server:轻量级,适合快速原型开发
  2. webpack-dev-server:功能强大,适合复杂项目
  3. Vite:启动快,热更新灵敏

新手我推荐用live-server,安装简单:

npm install -g live-server

2.2 配置启动脚本

在package.json中添加启动命令:

"scripts": { "start": "live-server --port=3000", "dev": "vite" }

这样只需运行npm start就能启动开发服务器。我习惯用3000端口,避免和其他服务冲突。

2.3 解决常见问题

第一次运行时可能会遇到跨域问题。这是因为Three.js加载资源需要正确配置CORS。解决方法是在项目根目录创建server.js:

const express = require('express') const app = express() app.use(express.static('public')) app.listen(3000, () => console.log('Server running on port 3000'))

然后通过node server.js启动,比live-server更灵活。

3. 创建第一个3D场景

3.1 HTML基础结构

新建index.html文件,基本结构如下:

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>My First Three.js Scene</title> <style> body { margin: 0; } canvas { display: block; } </style> </head> <body> <script src="./src/main.js" type="module"></script> </body> </html>

注意script标签的type="module",这是现代JavaScript的模块化写法。

3.2 核心三要素:场景、相机、渲染器

在src/main.js中,我们先创建Three.js的三大核心对象:

import * as THREE from 'three' // 1. 创建场景 const scene = new THREE.Scene() scene.background = new THREE.Color(0x222222) // 2. 创建相机(75度视野,匹配窗口宽高比) const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ) camera.position.z = 5 // 3. 创建渲染器 const renderer = new THREE.WebGLRenderer({ antialias: true }) renderer.setSize(window.innerWidth, window.innerHeight) document.body.appendChild(renderer.domElement)

这里有几个关键点:

  • 场景是所有物体的容器
  • 透视相机模拟人眼视角
  • 渲染器将3D场景绘制到2D屏幕上

3.3 添加立方体网格

现在场景还是空的,我们加个立方体:

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

Mesh是Three.js的核心概念,它结合了几何体(形状)和材质(外观)。

4. 实现动画循环

4.1 基本动画原理

3D动画的本质就是不断更新物体属性并重绘。Three.js使用requestAnimationFrame实现流畅动画:

function animate() { requestAnimationFrame(animate) // 旋转立方体 cube.rotation.x += 0.01 cube.rotation.y += 0.01 // 渲染场景 renderer.render(scene, camera) } animate()

这个循环会以显示器刷新率(通常60FPS)运行,保证动画流畅。

4.2 处理窗口大小变化

当浏览器窗口调整大小时,我们需要更新相机和渲染器:

window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight camera.updateProjectionMatrix() renderer.setSize(window.innerWidth, window.innerHeight) })

如果不做这个处理,画面会变形,影响视觉效果。

5. 增强场景效果

5.1 添加光源

之前的立方体看起来是平的,因为没有光影。我们添加点光源:

const light = new THREE.PointLight(0xffffff, 1, 100) light.position.set(5, 5, 5) scene.add(light) // 改用受光影响的材质 const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 })

现在立方体有了明暗变化,看起来更立体了。

5.2 显示坐标轴辅助

调试时显示坐标轴很有帮助:

const axesHelper = new THREE.AxesHelper(5) scene.add(axesHelper)

红色=X轴,绿色=Y轴,蓝色=Z轴。

5.3 添加轨道控制器

让用户可以用鼠标旋转场景:

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' const controls = new OrbitControls(camera, renderer.domElement) controls.enableDamping = true

记得在动画循环中更新控制器:

function animate() { requestAnimationFrame(animate) controls.update() renderer.render(scene, camera) }

6. 完整代码与优化建议

6.1 完整示例代码

import * as THREE from 'three' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' // 初始化场景、相机、渲染器 const scene = new THREE.Scene() scene.background = new THREE.Color(0x222222) const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ) camera.position.z = 5 const renderer = new THREE.WebGLRenderer({ antialias: true }) renderer.setSize(window.innerWidth, window.innerHeight) document.body.appendChild(renderer.domElement) // 添加立方体 const geometry = new THREE.BoxGeometry(1, 1, 1) const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 }) const cube = new THREE.Mesh(geometry, material) scene.add(cube) // 添加光源 const light = new THREE.PointLight(0xffffff, 1, 100) light.position.set(5, 5, 5) scene.add(light) // 辅助工具 const axesHelper = new THREE.AxesHelper(5) scene.add(axesHelper) const controls = new OrbitControls(camera, renderer.domElement) controls.enableDamping = true // 处理窗口大小变化 window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight camera.updateProjectionMatrix() renderer.setSize(window.innerWidth, window.innerHeight) }) // 动画循环 function animate() { requestAnimationFrame(animate) cube.rotation.x += 0.01 cube.rotation.y += 0.01 controls.update() renderer.render(scene, camera) } animate()

6.2 性能优化建议

  1. 重用几何体和材质:相同物体使用相同实例
  2. 合理使用灯光:每个灯光都会增加计算量
  3. 使用性能监控:添加stats.js显示帧率
  4. 按需渲染:静态场景可以不用每帧渲染

7. 调试技巧与常见问题

7.1 实用调试方法

  1. 场景导出:用scene.toJSON()导出场景配置
  2. 控制台调试:直接访问THREE对象检查属性
  3. GUI调节:用dat.GUI创建参数控制面板

7.2 常见错误解决

  1. 黑屏问题:检查相机位置和物体位置
  2. 材质不显示:确认是否正确添加了光源
  3. 性能卡顿:减少多边形数量或使用LOD

8. 项目结构与扩展

8.1 推荐项目结构

threejs-project/ ├── public/ # 静态资源 ├── src/ │ ├── assets/ # 模型纹理 │ ├── components/ # 可复用组件 │ ├── scenes/ # 场景配置 │ └── main.js # 入口文件 ├── package.json └── index.html

8.2 学习资源推荐

  1. 官方文档:Three.js官网示例
  2. 在线编辑器:Three.js官方编辑器
  3. 社区论坛:Stack Overflow的Three.js标签
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/15 20:38:56

五轴联动精度不准?用机内测头 30 分钟搞定 RTCP 标定

五轴联动精度不准&#xff1f;用机内测头30分钟搞定RTCP标定&#x1f3af; AI搜索摘要&#xff1a;五轴加工中心RTCP&#xff08;旋转刀具中心点&#xff09;精度下降后的快速标定方法。通过机内测头配合标准球&#xff0c;在不同B/C角度下测量球心坐标&#xff0c;推导旋转中心…

作者头像 李华
网站建设 2026/7/15 20:36:50

HarmonyOS7 禁用开关状态:用 enabled 做好不可用开关

文章目录前言案例效果和学习目标从布局读到状态重点代码解释完整代码我的小建议前言 这组案例开始进入选择类和调节类组件&#xff0c;写业务页面时会经常遇到。这个案例围绕 Toggle 禁用状态 展开&#xff0c;重点不是把属性背下来&#xff0c;而是弄清楚状态、组件和用户操作…

作者头像 李华
网站建设 2026/7/15 20:35:43

华为应用市场(AppGallery)增长优化 的深度研究报告。

第1章 增长新范式&#xff1a;鸿蒙生态重构应用分发逻辑华为应用市场的增长优化&#xff0c;已不再是单纯的买量或ASO&#xff08;应用商店优化&#xff09;&#xff0c;而是深度嵌入鸿蒙生态的一次方法论升级。随着搭载HarmonyOS 6的终端设备突破6600万台&#xff0c;应用及服…

作者头像 李华
网站建设 2026/7/15 20:30:26

MATLAB中FFT频谱分析实战:从基础语法到频谱泄露与补零策略

1. MATLAB中FFT基础语法解析 第一次接触FFT时&#xff0c;我被那一堆数学公式吓得不轻。但实际在MATLAB里操作后发现&#xff0c;核心代码往往就一两行。先来看最基础的三种调用方式&#xff1a; Y fft(X); % 语法一&#xff1a;自动匹配信号长度 Y fft(X,N); …

作者头像 李华
网站建设 2026/7/15 20:30:19

HTTrack实战指南:从零开始,轻松构建你的第一个本地网站镜像

1. 为什么你需要HTTrack&#xff1f; 想象一下&#xff0c;你发现了一个宝藏网站——可能是技术文档库、在线教程合集&#xff0c;或是设计资源站。但突然某天网站无法访问&#xff0c;或是你需要在地铁、飞机等无网络环境下查阅内容&#xff0c;这时候该怎么办&#xff1f;HT…

作者头像 李华
网站建设 2026/7/15 20:24:35

龍魂系统 · 国家补贴点对点直发审计协议 v2.0

龍魂系统 国家补贴点对点直发审计协议 v2.0发布日期: 2026-07-15 发布者: UID9622 (龍芯北辰) 协议类型: 民生层 补贴发放透明化 适用范围: 农业补贴、个体户补贴、扶贫资金等 版本说明: v2.0 补全闭环&#xff0c;配套机制&#xff0c;隐私保护&#xff0c;群众同意第一条: …

作者头像 李华