在前端 3D 可视化项目中,Vue3 + Three.js 是一种常见组合。Vue3 提供了高效的响应式框架,而 Three.js 则负责 3D 渲染与模型处理。本文将详细介绍在 Vue3 中如何使用 Three.js 生成并导出模型,以及过程中需要注意的细节。
一、项目环境搭建
安装依赖
npm install three
npm install three-stdlib # 包含常用导出/加载工具
在 Vue3 组件中引入
<script setup>
import * as THREE from "three";
import { GLTFExporter } from "three-stdlib";
</script>
二、初始化 Three.js 场景
在 Vue3 中推荐使用 onMounted 来初始化 Three.js,避免 DOM 未挂载导致的渲染问题。
<template>
<div ref="canvasContainer" class="three-container"></div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import * as THREE from "three";
const canvasContainer = ref(null);
onMounted(() => {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, canvasContainer.value.clientWidth / canvasContainer.value.clientHeight, 0.1, 1000);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(canvasContainer.value.clientWidth, canvasContainer.value.clientHeight);
canvasContainer.value.appendChild(renderer.domElement);
// 添加简单几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// 光照
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5, 5, 5);
scene.add(light);
// 动画循环
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
});
</script>
<style>
.three-container {
width: 100%;
height: 500px;
background: #111;
}
</style>
三、模型导出(GLTF/OBJ/STL)
Three.js 提供 导出工具,常见格式有 GLTF、OBJ、STL。
1. 使用 GLTFExporter
import { GLTFExporter } from "three-stdlib";
function exportGLTF(scene) {
const exporter = new GLTFExporter();
exporter.parse(
scene,
(gltf) => {
const blob = new Blob([JSON.stringify(gltf)], { type: "application/json" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "model.gltf";
link.click();
URL.revokeObjectURL(url);
},
{ binary: false } // 如果需要导出 .glb,设置 true
);
}
2. 导出为 OBJ
import { OBJExporter } from "three-stdlib";
function exportOBJ(scene) {
const exporter = new OBJExporter();
const objString = exporter.parse(scene);
const blob = new Blob([objString], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "model.obj";
link.click();
URL.revokeObjectURL(url);
}
3. 导出为 STL
import { STLExporter } from "three-stdlib";
function exportSTL(scene) {
const exporter = new STLExporter();
const stlString = exporter.parse(scene);
const blob = new Blob([stlString], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "model.stl";
link.click();
URL.revokeObjectURL(url);
}
四、细节与注意事项
DOM 与 Vue 生命周期
- Three.js 必须在 onMounted 后初始化,否则渲染容器未挂载。
- 若需要销毁 Three.js 场景,应在 onUnmounted 中释放内存。
相机与渲染器的自适应
- 在窗口缩放时,需要更新相机宽高比和渲染器大小:
window.addEventListener("resize", () => {
camera.aspect = canvasContainer.value.clientWidth / canvasContainer.value.clientHeight;
camera.updateProjectionMatrix();
renderer.setSize(canvasContainer.value.clientWidth, canvasContainer.value.clientHeight);
});
模型优化
- 导出前可调用 scene.traverse 进行 Mesh 合并或材质简化。
- 使用 THREE.BufferGeometryUtils.mergeBufferGeometries 可减少 draw calls。
GLTF 导出兼容性
- 如果导出 .glb,必须 { binary: true }。
- 材质中 MeshBasicMaterial、MeshStandardMaterial 兼容性较好,ShaderMaterial 可能无法正确导出。
性能与内存管理
- 导出前可 renderer.dispose() 或清理不必要的对象,避免导出冗余数据。
- 大模型导出可能导致卡顿,建议异步执行或使用 Web Worker。
五、总结
在 Vue3 中使用 Three.js 生成与导出模型时,需要特别注意 Vue 生命周期、相机自适应、材质兼容性、内存释放 等细节。GLTF 格式是最推荐的导出方式,兼容性强,适合 Web 与 AR/VR 使用。如果对文件大小和加载速度有要求,可以进一步结合压缩方案(如 Draco 压缩)。
3263

被折叠的 条评论
为什么被折叠?



