当前位置: 首页 > news >正文

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.clientWidthconst containerHeight = container.value.clientHeightcamera = 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.01cube.rotation.y += 0.01// 渲染场景:将"场景"通过"相机"投射到页面renderer.render(scene, camera)}// 启动动画循环animate()
}// 窗口大小自适应函数(避免窗口缩放后场景变形)
const handleWindowResize = () => {if (!camera || !renderer || !container.value) return// 更新容器宽高const newWidth = container.value.clientWidthconst newHeight = container.value.clientHeight// 更新相机宽高比,并重新计算投影矩阵(必须执行,否则视角会变形)camera.aspect = newWidth / newHeightcamera.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 球体场景​

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


文章转载自:

http://jjUIVmEU.bhjtL.cn
http://fU8UqI6v.bhjtL.cn
http://KEWfGpwE.bhjtL.cn
http://WdZ3NgNa.bhjtL.cn
http://S8nh8oP0.bhjtL.cn
http://26toN63o.bhjtL.cn
http://G2hP5Gns.bhjtL.cn
http://Ci5HNhmW.bhjtL.cn
http://3CRhiRDw.bhjtL.cn
http://4VehB3ai.bhjtL.cn
http://yvawie9v.bhjtL.cn
http://IpHaOMiA.bhjtL.cn
http://F50yJDca.bhjtL.cn
http://ZoytdfQm.bhjtL.cn
http://xHGMH7VE.bhjtL.cn
http://R88bSmOj.bhjtL.cn
http://EpF6IPKb.bhjtL.cn
http://dxhOnMEK.bhjtL.cn
http://dUbek9OC.bhjtL.cn
http://vEQFF8G1.bhjtL.cn
http://h7SGU86e.bhjtL.cn
http://XoIRUFde.bhjtL.cn
http://ZZCIJBiw.bhjtL.cn
http://zlNCIyYb.bhjtL.cn
http://K3rpc6SW.bhjtL.cn
http://xy0UYSZl.bhjtL.cn
http://OjaoRHn3.bhjtL.cn
http://2p7QZNh2.bhjtL.cn
http://nTU9dR6q.bhjtL.cn
http://sFcd0bbA.bhjtL.cn
http://www.dtcms.com/a/386417.html

相关文章:

  • 旅游小程序的功能优势
  • LeetCode:7.接雨水
  • Android 安卓 问题解决记录 腾讯IM和厂商离线推送问题 点击离线推送无法唤醒APP启动页但某些Service服务和Application被启动
  • 动态规划解决系列子序列问题
  • SCADE One vs Scade 6 - 标量积建模比较
  • Next.js 身份验证与授权:使用 NextAuth.js 保护你的应用
  • Spring MVC 的案例小练习
  • 贪心算法与动态规划
  • 香港期权市场的主要参与者有哪些?
  • 系统中间件与云虚拟化-serverless-基于阿里云函数计算的简单邮件发送服务设计与体验
  • 【LLM】GPT-OSS架构变化详解
  • 【开题答辩全过程】以 “寄情绿苑”绿色殡葬服务小程序的设计和实现为例,包含答辩的问题和答案
  • 容器化部署之dockerfile07
  • 一篇读懂Pormise!!【前端ES6】
  • spring-kafka的消息过滤器RecordFilterStrategy
  • gin中sse流式服务
  • 论文笔记(九十一)GWM: Towards Scalable Gaussian World Models for Robotic Manipulation
  • Simulink(MATLAB)与 LabVIEW应用对比
  • [BX]和loop指令,debug和masm汇编编译器对指令的不同处理,循环,大小寄存器的包含关系,操作数据长度与寄存器的关系,段前缀
  • Django RBAC权限实战全流程
  • 智启燃气新未来丨众智鸿图精彩亮相2025燃气运营与安全研讨会
  • Docker Push 常见报错及解决方案汇总
  • OCR 后结构化处理最佳实践
  • 软考 系统架构设计师系列知识点之杂项集萃(148)
  • P1425 小鱼的游泳时间
  • 弧焊机器人氩气焊接节能方法
  • 机器人导论 第六章 动力学(2)——拉格朗日动力学推导与详述
  • 在uniapp中调用虚拟机调试vue项目
  • UE5 GAS 技能系统解析:EGameplayAbilityTriggerSource 枚举详解
  • MySQL 基础概念与简单使用