Three.js 入门实战:基于 Vue3 做一个可拖拽的 3D 编辑器
Three.js 入门实战:基于 Vue3 做一个可拖拽的 3D 编辑器
前言
如果你是第一次接触 Three.js,这篇文章会带你从 0 到 1 建立完整认知:
- Three.js 到底是什么。
- 核心概念有哪些。
- 怎么在真实项目里用起来。
- 新手最容易踩哪些坑。
本文不是纯理论,而是结合我自己写的一个真实项目 drag-3D-three 来讲解。这个项目是一个 3D/2D 可视化大屏编辑器,Three.js 部分支持拖拽创建几何体、加载模型、选择元素、修改属性和保存案例。
技术栈:Vue 3 + TypeScript + Vite + Three.js + Pinia
一、Three.js 是什么
Three.js 是一个运行在浏览器中的 3D 图形库,它基于 WebGL 做了高级封装。
你可以把它理解成:
- WebGL 是底层图形 API,能力强但很底层。
- Three.js 是更易用的“3D 开发工具箱”。
- 你不需要直接写复杂着色器,也能快速搭建 3D 场景。
Three.js 适合做什么:
- 3D 数据可视化。
- 数字孪生大屏。
- 在线 3D 编辑器。
- 模型展示页。
- 小型网页 3D 互动。
二、先记住 7 个核心概念(新手必会)
1. Scene(场景)
所有 3D 对象都放在 Scene 里。它相当于“舞台”。
1 | const scene = new THREE.Scene() |
2. Camera(相机)
相机决定你从哪里看场景。
常用的是透视相机:PerspectiveCamera。
1 | const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000) |
3. Renderer(渲染器)
渲染器负责把场景画到 canvas 上。
1 | const renderer = new THREE.WebGLRenderer({ canvas, antialias: true }) |
4. Geometry + Material + Mesh
一个能看到的 3D 物体通常由三部分组成:
-
Geometry:形状(立方体、球体等)。 -
Material:材质(颜色、金属感、粗糙度等)。 -
Mesh:几何体 + 材质的组合。
1 | const geometry = new THREE.BoxGeometry(5, 5, 5) |
5. Light(光照)
如果你用的是标准材质(MeshStandardMaterial),必须有光,不然会很黑。
1 | scene.add(new THREE.AmbientLight(0xffffff, 0.5)) |
6. Controls(控制器)
项目里使用 OrbitControls,让用户能旋转、缩放、平移视角。
7. Animation Loop(动画循环)
Three.js 渲染通常放在循环里持续执行:
1 | function animate() { |
只要你掌握这 7 点,已经能做出基础可交互场景。
三、基于我这个项目看 Three.js 怎么“落地”
下面结合我项目 drag-3D-three 的核心文件 src/components/ThreeDWorkspace.vue 看实战。
1. 初始化 3D 工作区
在 initThreeJS 里完成了完整初始化流程:
- 创建
scene、camera、renderer。 - 注册
OrbitControls。 - 添加环境光、平行光、网格辅助线
GridHelper。 - 初始化
Raycaster用于点击选中。 - 绑定
resize、click、dragover、drop等事件。
这就是一个标准的 Three.js 工程启动模板。
2. 元素数据结构(非常关键)
项目定义了统一元素结构,类似:
1 | interface Element { |
为什么新手要重视这一步:
- 数据结构统一后,渲染逻辑可复用。
- 能轻松做保存、撤销、模板化。
- 后续扩展动画、材质、权限都更顺。
3. 创建基础几何体
项目按 type 分发创建几何体:
-
cube->BoxGeometry -
sphere->SphereGeometry -
cylinder->CylinderGeometry -
pyramid->ConeGeometry
然后统一材质和位置设置,最后 scene.add(mesh)。
4. 加载自定义模型(GLTF/OBJ/FBX/STL)
项目支持多种模型格式,按扩展名选择对应 Loader:
-
GLTFLoader -
OBJLoader -
FBXLoader -
STLLoader
加载后通过 Box3 计算模型包围盒,自动缩放到目标尺寸。这一步很实用,能避免不同模型源比例不一致的问题。
5. 用 Raycaster 做“点击选中”
点击画布后,先把鼠标坐标转换到标准化设备坐标,再发射射线检测相交对象。命中后通过 userData.elementId 找到业务元素。
这个思路是 Three.js 交互的基础技能。
6. 拖拽放置:把 HTML 拖拽和 3D 场景打通
项目中左侧元素卡片可拖拽,拖拽数据通过 dataTransfer 传入画布:
- 工具栏组件写入
application/json。 - 工作区
handleDrop解析 JSON。 - 根据鼠标位置生成 3D 元素并发出
element-created。
这就是“低代码编辑器”的核心路径。
四、新手从零跑起来(实操步骤)
1. 安装和启动
1 | npm install |
2. 使用路径
- 进入编辑页。
- 左侧拖一个“立方体”到中间画布。
- 鼠标右键/滚轮配合
OrbitControls调整视角。 - 点击元素,在右侧修改位置、尺寸、颜色、编号。
- 点击保存,写入案例库。
3. 你会学到什么
完成以上步骤后,你会自然掌握:
- Scene/Camera/Renderer 的协作关系。
- Three.js 和 Vue 组件的通信方式。
- 基础几何体与外部模型的统一管理。
- 射线拾取和拖拽交互。
- Three.js 项目中的状态持久化思路。
五、常见问题与避坑清单
1. 场景里什么都看不见
排查顺序:
- 相机是否对着物体。
- 是否有光照。
- 物体是否被加到 scene。
- 动画循环是否在执行。
- canvas 尺寸是否正确。
2. 模型加载失败
排查顺序:
- 模型路径是否可访问。
- 文件扩展名是否匹配 Loader。
- 是否有跨域问题。
- 控制台错误信息是否显示解析失败。
3. 拖拽位置不准
当前项目使用屏幕坐标线性映射,新手阶段够用;如果你追求更精确,建议升级为“射线与地面平面求交”方案。
4. 画面卡顿
常见原因:
- 每次数据变化都全量重建 mesh。
- 几何体分段数设置太高。
- 频繁创建对象但没有释放资源。
六、进阶建议:从教程走向实战
如果你已经跑通我这个项目,下一步建议按这个顺序升级:
- 加
TransformControls(选中后可视化移动/旋转/缩放)。 - 实现元素分组和层级管理。
- 增加材质面板(透明度、贴图、发光)。
- 加载压缩模型(Draco)优化首屏。
- 增量更新渲染,减少全量重建。
- 引入截图功能生成案例缩略图。
七、总结
Three.js 入门最怕两件事:
- 只看 API,不做项目。
- 直接做复杂效果,基础不稳。
这篇教程给你的路径是:
- 先吃透核心概念(场景、相机、渲染器、光照、Mesh)。
- 用真实项目练习交互(拖拽、选中、更新、持久化)。
- 再逐步走向工程化(性能、架构、可扩展性)。
当你能独立搭出一个可拖拽编辑器时,就已经不再是 Three.js 初学者了。
项目求个 Star
如果这篇文章或这个项目对你有帮助,欢迎访问仓库并点一个 Star:
https://github.com/hujinbin/drag-3D-three
你的每一个 Star,都会让我更有动力持续更新:
- 新手友好的 Three.js 示例。
- 更完整的编辑器能力(变换控制、材质系统、分组层级)。
- 更实用的工程化优化(性能、资源管理、可维护性)。
也欢迎提 Issue 或 PR,一起把这个项目打磨成更好用的 Three.js 学习模板。