效果大概这样,这个宝箱模型是直接初始化就显示的,人物模型是自己本地添加上去的,代码如下。
<template><div class="container" ref="container"><el-row><el-col :span="24"><div class="grid-content ep-bg-purple-dark"></div><el-tabs v-model="activeTab" class="demo-tabs" @tab-click="handleClick"><el-tab-pane label="3d模型" name="first"><input type="file" accept=".obj,.pltf,.fbx" @change="handleFileUpload"><div ref="modelContainer"></div></el-tab-pane></el-tabs></el-col></el-row></div>
</template><script>
import { ref, reactive, onMounted,getCurrentInstance} from 'vue'
import * as THREE from 'three'
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { AmbientLight, DirectionalLight } from 'three';export default {setup() {const model = ref(null);const container = ref(null)const modelContainer = ref(null)const previewContainer = ref(null);const pond = FilePond.create(inputElement);const state = reactive({uploadedFile: null,modelLoaded: false})let scene = null let controls = nullonMounted(() => {// 初始化场景scene = new THREE.Scene() // 将 scene 赋值// 初始化相机clet camera = new THREE.PerspectiveCamera(75,container.value.clientWidth / container.value.clientHeight,//纵横比0.1,//近截面距离1000//远截面距离)camera.position.z = 5// 初始化渲染器let renderer = new THREE.WebGLRenderer({ antialias: true })renderer.setSize(container.value.clientWidth, container.value.clientHeight)modelContainer.value.appendChild(renderer.domElement)// 添加光源const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); // 环境光const directionalLight = new THREE.DirectionalLight(0xffffff, 1); // 平行光directionalLight.position.set(1, 1, 1);scene.add(ambientLight);scene.add(directionalLight);// 初始化控制器initOrbitControls(camera, renderer)// 加载obj模型// const loader = new OBJLoader()// loader.load(// './public/static/obj/man.obj',// (object) => {// // 加载成功后的回调函数// // 在这里处理加载的模型对象// handleModelLoaded(object, scene) // 将 scene 作为参数传递// },// (xhr) => {// // 加载过程中的回调函数// console.log((xhr.loaded / xhr.total) * 100 + '% loaded')// },// (error) => {// // 加载失败的回调函数// console.error('加载失败', error)// }// )// 加载gltf模型const loader = new GLTFLoader();loader.load('./public/static/obj/scene.gltf',(gltf) => {scene.add(gltf.scene);},undefined,(error) => {console.error('加载失败', error);});// 循环渲染const animate = () => {requestAnimationFrame(animate)renderer.render(scene, camera) }animate()})// 更改颜色const handleModelLoaded = (object, scene) => {if (scene) {object.traverse((child) => {if (child instanceof THREE.Mesh) {child.material.color.set('#ff0000') }})scene.add(object)} else {console.error('Scene is not defined')}}// 控制器function initOrbitControls(camera, renderer) {controls = new OrbitControls(camera, renderer.domElement)controls.enableDamping = truecontrols.enableZoom = truecontrols.autoRotate = false// 禁用自动旋转controls.autoRotateSpeed = 3// 设置自动旋转速度controls.enablePan = true// 启用相机平移controls.enableKeys = true// 启用键盘控制controls.keyPanSpeed = 7//平移速度controls.keys = {LEFT: 37,UP: 38,RIGHT: 39,BOTTOM: 40}// 键盘控制按键码设置}const getBigectURL = (event) => {const current = event.target.files[0]const fileReader = new FileReader()fileReader.readAsDataURL(current)fileReader.onload = (e) => {state.videoSrc = e.currentTarget.result}}return {container,modelContainer,...state,initOrbitControls,activeTab: 'first',videoSrc: '',container,state,model,}}
}
</script><style>
.container {height: 100%;width: 100%;
}</style>