在 Vue 中使用 Three.js 渲染 GLB 格式模型
在 Vue 项目中渲染 GLB 格式的 3D 模型需要结合 Three.js 和 GLTFLoader。以下是完整的实现步骤:
- 安装必要的依赖
首先安装 Three.js 和 GLTFLoader:
npm install three @types/three
- 页面中加载和渲染 GLB 模型
(glb模型放入本地/assets/public文件夹下了)
<template><div ref="container" style="width: 100%; height: 100vh;"></div>
</template><script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import url from '@/assets/public/jizu.glb'const container = ref(null);let scene, camera, renderer, controls, animationId;onMounted(() => {// 1. 初始化场景scene = new THREE.Scene();scene.background = new THREE.Color(0xaaaaaa);// 2. 初始化相机const width = container.value.clientWidth;const height = container.value.clientHeight;camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);camera.position.set(0, 2, 5);// 3. 初始化渲染器renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(width, height);container.value.appendChild(renderer.domElement);// 4. 添加光源const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);scene.add(ambientLight);const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);directionalLight.position.set(5, 10, 7);scene.add(directionalLight);// 5. 添加轨道控制器controls = new OrbitControls(camera, renderer.domElement);controls.target.set(0, 1, 0);controls.update();// 6. 加载 GLB 模型const loader = new GLTFLoader();console.log(loader,'111')loader.load(url, // 替换成你的模型路径(gltf) => {console.log(gltf,'222')scene.add(gltf.scene);},undefined,(error) => {console.error('加载模型失败:', error);});// 7. 动画循环function animate() {animationId = requestAnimationFrame(animate);controls.update();renderer.render(scene, camera);}animate();// 8. 监听窗口大小变化window.addEventListener('resize', onWindowResize);
});function onWindowResize() {if (!container.value) return;const width = container.value.clientWidth;const height = container.value.clientHeight;camera.aspect = width / height;camera.updateProjectionMatrix();renderer.setSize(width, height);
}onBeforeUnmount(() => {window.removeEventListener('resize', onWindowResize);cancelAnimationFrame(animationId);controls.dispose();renderer.dispose();// 清理场景中的所有对象,防止内存泄漏scene.traverse((obj) => {if (obj.geometry) obj.geometry.dispose();if (obj.material) {if (Array.isArray(obj.material)) {obj.material.forEach((m) => m.dispose());} else {obj.material.dispose();}}});scene.clear();
});
</script>
如果使用的是vite可能会报错,在vite.config.js文件下加入:assetsInclude: ['**/*.glb'], // 明确包含GLB文件
import { fileURLToPath, URL } from 'node:url'import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'export default defineConfig({assetsInclude: ['**/*.glb'], // 明确包含GLB文件server: {https: false,// host: "0.0.0.0",port: 9001,open: true,cors: true,strictPort: false,proxy: {'/api': {target: 'http://1.117.236.127',changeOrigin: true,rewrite: (path) => path.replace("/api", "")},}},
})