Three.js 开发实战教程(一):环境搭建与第一个 3D 场景

本专栏将围绕 Three.js 核心能力,从基础到进阶,通过实战案例带大家掌握 3D 可视化开发。第一篇聚焦「入门第一关」—— 解决环境搭建问题,并实现第一个可交互的 3D 场景,为后续学习打下基础。

一、Three.js 是什么?​

Three.js 是基于 WebGL 的 JavaScript 3D 库,它封装了 WebGL 的复杂底层 API,让开发者无需深入图形学原理,就能快速创建 3D 场景、模型与动画。其核心应用场景包括:​

  • 3D 产品展示(电商商品预览、工业设备拆解)​
  • 数据可视化(GIS 地理信息、大屏数据 3D 呈现)​
  • 轻量游戏开发(Web 端小游戏、互动场景)​
  • 虚拟仿真(教育课件、医疗模拟演示)​

二、开发环境搭建(Vue3 + Vite + Three.js)​

本专栏统一采用「Vue3 + Vite」技术栈(前端主流组合,打包速度快、开发体验佳),以下是完整搭建步骤:​

1. 创建 Vite 项目​

确保已安装 Node.js(建议 v16+),打开终端执行以下命令:

# 创建项目(项目名自定义,示例为threejs-demo)
npm create vite@latest threejs-demo -- --template vue

# 进入项目目录
cd threejs-demo

# 安装项目依赖
npm install

# 启动开发服务(默认端口5173,可在vite.config.js中修改)
npm run dev

2. 安装 Three.js 相关依赖​

需安装 Three.js 核心包与类型定义文件(非 TS 项目安装类型定义,可获得更好的 IDE 语法提示):

npm install three @types/three

3. 项目核心目录梳理​

后续实战案例将重点关注src/components目录,核心结构如下:

threejs-demo/
├─ src/
│  ├─ components/  # 存放3D相关组件(重点目录)
│  ├─ App.vue      # 项目入口组件
│  └─ main.js      # 项目入口文件(初始化Vue实例)
└─ package.json    # 项目依赖与脚本配置

三、实战:创建第一个 3D 场景(旋转立方体)​

本次实战将实现 Three.js 最基础的「三要素 + 物体 + 动画」结构,最终呈现「彩色立方体绕轴旋转」的效果,帮助理解 3D 场景的核心构成。​

1. 核心概念解析​

创建 Three.js 3D 场景,必须包含三大核心组件,缺一不可:​

组件​

核心作用​

通俗类比​

Scene(场景)​

承载 3D 物体、灯光、相机的 "容器"​

电影的「拍摄场地」​

Camera(相机)​

决定观察视角(从哪个角度看场景)​

电影的「摄像机」​

Renderer(渲染器)​

将场景渲染到浏览器页面​

电影的「放映机」​

2. 完整代码实现(创建 ThreeDemo.vue 组件)​

在src/components目录下新建ThreeDemo.vue文件,代码附带详细注释,便于理解每一步作用:

<template>
  <!-- 3D场景容器:必须设置宽高,否则渲染器无法正常显示 -->
  <div class="three-container" ref="container"></div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
// 导入Three.js核心模块(* as THREE表示导入所有核心功能)
import * as THREE from 'three'

// 声明核心变量:容器引用、场景/相机/渲染器实例、立方体对象、动画循环ID
const container = ref(null)
let scene, camera, renderer, cube, animationId

// 初始化3D场景的核心函数
const initScene = () => {
  // --------------------------
  // 步骤1:创建场景(Scene)
  // --------------------------
  scene = new THREE.Scene()
  // 可选:设置场景背景色(默认黑色,这里设为浅灰色提升视觉体验)
  scene.background = new THREE.Color(0xf0f0f0)

  // --------------------------
  // 步骤2:创建透视相机(模拟人眼视角)
  // 参数说明:fov(视角角度)、aspect(宽高比)、near(近裁剪面)、far(远裁剪面)
  // --------------------------
  const containerWidth = container.value.clientWidth
  const containerHeight = container.value.clientHeight
  camera = new THREE.PerspectiveCamera(75, containerWidth / containerHeight, 0.1, 1000)
  // 调整相机位置:默认在(0,0,0),与立方体重叠会看不到,故沿z轴后移5个单位
  camera.position.z = 5

  // --------------------------
  // 步骤3:创建WebGL渲染器
  // --------------------------
  renderer = new THREE.WebGLRenderer({ antialias: true }) // antialias开启抗锯齿,画面更平滑
  renderer.setSize(containerWidth, containerHeight) // 渲染尺寸与容器一致
  // 将渲染器生成的canvas元素,添加到页面容器中
  container.value.appendChild(renderer.domElement)

  // --------------------------
  // 步骤4:创建3D物体(立方体+彩色材质)
  // --------------------------
  // 4.1 几何体:BoxGeometry(宽, 高, 深),定义立方体的形状
  const cubeGeometry = new THREE.BoxGeometry(2, 2, 2)
  // 4.2 材质:MeshNormalMaterial自带彩色效果,无需额外灯光
  const cubeMaterial = new THREE.MeshNormalMaterial({
    wireframe: false, // 是否显示线框(true时仅显示轮廓,适合调试)
    transparent: false, // 是否透明
    opacity: 1 // 透明度(0-1,仅transparent为true时生效)
  })
  // 4.3 网格对象:几何体+材质的组合,是Three.js中可渲染的3D物体
  cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
  // 将立方体添加到场景中(未添加则不会被渲染)
  scene.add(cube)

  // --------------------------
  // 步骤5:添加动画循环(实现立方体旋转)
  // --------------------------
  const animate = () => {
    // 请求浏览器下一帧动画(浏览器优化机制,避免卡顿)
    animationId = requestAnimationFrame(animate)
    
    // 每帧更新立方体旋转角度(x轴、y轴各旋转0.01弧度)
    cube.rotation.x += 0.01
    cube.rotation.y += 0.01

    // 渲染场景:将"场景"通过"相机"投射到页面
    renderer.render(scene, camera)
  }
  // 启动动画循环
  animate()
}

// 窗口大小自适应函数(避免窗口缩放后场景变形)
const handleWindowResize = () => {
  if (!camera || !renderer || !container.value) return
  // 更新容器宽高
  const newWidth = container.value.clientWidth
  const newHeight = container.value.clientHeight
  // 更新相机宽高比,并重新计算投影矩阵(必须执行,否则视角会变形)
  camera.aspect = newWidth / newHeight
  camera.updateProjectionMatrix()
  // 更新渲染器尺寸
  renderer.setSize(newWidth, newHeight)
}

// Vue生命周期钩子:确保DOM加载完成后初始化场景
onMounted(() => {
  initScene()
  // 监听窗口缩放事件
  window.addEventListener('resize', handleWindowResize)
})

// Vue生命周期钩子:组件销毁时清理资源(避免内存泄漏)
onUnmounted(() => {
  // 移除窗口缩放监听
  window.removeEventListener('resize', handleWindowResize)
  // 停止动画循环
  cancelAnimationFrame(animationId)
  // 销毁渲染器(释放GPU资源)
  renderer.dispose()
})
</script>

<style scoped>
/* 3D容器必须设置宽高,否则渲染器生成的canvas会是默认的100x100像素 */
.three-container {
  width: 100vw;
  height: 80vh;
  margin-top: 20px;
}
</style>

3. 在 App.vue 中引用组件​

修改src/App.vue,引入并使用上述创建的ThreeDemo组件,实现页面入口:

<template>
  <div id="app">
    <h1 style="text-align: center; margin-top: 20px;">Three.js 第一个3D场景</h1>
    <!-- 引入3D场景组件 -->
    <ThreeDemo />
  </div>
</template>

<script setup>
// 导入ThreeDemo组件
import ThreeDemo from './components/ThreeDemo.vue'
</script>

<style>
/* 全局样式重置:消除默认边距,避免页面布局偏移 */
body {
  margin: 0;
  padding: 0;
}
</style>

4. 运行效果预览​

启动项目后访问http://localhost:5173,可看到以下效果:​

  • 浅灰色背景的 3D 场景​
  • 一个彩色立方体沿 x 轴、y 轴缓慢旋转​
  • 拖动窗口调整大小,场景会自动适配,无变形​

四、新手必看:关键注意事项​

  1. 容器宽高不可省略:渲染器依赖容器宽高确定 canvas 尺寸,未设置会导致场景显示异常(默认 100x100 像素)。​
  2. 相机位置需合理调整:相机默认在 (0,0,0),若与物体重叠会 "看不到" 物体,需通过camera.position调整(如沿 z 轴后移)。​
  3. 材质选择适配场景:​
  • MeshBasicMaterial:基础材质,不依赖灯光,适合调试。​
  • MeshNormalMaterial:彩色自发光材质,无需额外灯光,适合入门演示。​
  • 后续将讲解依赖灯光的材质(如MeshLambertMaterial)。​

4.组件销毁需清理资源:必须停止动画循环(cancelAnimationFrame)并销毁渲染器(renderer.dispose),避免内存泄漏。​

五、专栏预告​

下一篇将深入 Three.js 的几何体与材质系统,内容包括:​

  • 常用几何体(平面、球体、圆柱体等)的创建与参数配置​
  • 材质分类与应用场景(基础材质、光照材质、纹理材质)​
  • 实战:创建带纹理贴图的 3D 球体场景​

若操作中遇到问题,可在评论区留言,后续将优先针对高频问题补充说明!​

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YAY_tyy

坚持不设置VIP文章

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值