Appearance
Three.js模型的使用
简单实现一个3d模型的效果,简单介绍模型的使用
sh
npm install three
npm install three
需要下载一个glb格式的3D模型文件
js
<template>
<div class="about">
<div ref="container" class="canvas-container"></div>
</div>
</template>
<script setup>
import { onMounted, onBeforeUnmount, ref } from 'vue'
import * as THREE from 'three'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
const container = ref(null)
let scene = null
let camera = null
let renderer = null
let mixer = null
let model = null
let animationId = null
const initScene = () => {
// 初始化场景
scene = new THREE.Scene()
scene.background = new THREE.Color(0xeeeeee)
// 初始化相机
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.set(5, 5, 5)
// 初始化渲染器
renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(container.value.clientWidth, container.value.clientHeight)
container.value.appendChild(renderer.domElement)
// 添加灯光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.8)
scene.add(ambientLight)
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5)
directionalLight.position.set(5, 5, 5)
scene.add(directionalLight)
}
const loadModel = () => {
const loader = new GLTFLoader()
// 替换成你的GLB模型路径
loader.load(
'/models/models.glb',
(gltf) => {
model = gltf.scene
scene.add(model)
// 如果有动画
if (gltf.animations.length > 0) {
mixer = new THREE.AnimationMixer(model)
const action = mixer.clipAction(gltf.animations[0])
action.play()
}
// 调整模型位置和缩放
model.position.set(5, 2, 0)
model.scale.set(5, 3, 1)
// 自动调整相机视角
const box = new THREE.Box3().setFromObject(model)
const center = box.getCenter(new THREE.Vector3())
camera.lookAt(center)
// 引入添加控制器,可以用鼠标控制模型
const controls = new OrbitControls(camera, renderer.domElement)
controls.target.copy(model.position)
controls.update()
controls.enableDamping = true
},
undefined,
(error) => {
console.error('Error loading model:', error)
}
)
}
const animate = () => {
// 更新动画
if (mixer) {
mixer.update(0.0167) // 60fps
}
renderer.render(scene, camera)
animationId = requestAnimationFrame(animate)
}
const handleResize = () => {
camera.aspect = container.value.clientWidth / container.value.clientHeight
camera.updateProjectionMatrix()
renderer.setSize(container.value.clientWidth, container.value.clientHeight)
}
onMounted(() => {
initScene()
loadModel()
animate()
window.addEventListener('resize', handleResize)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', handleResize)
cancelAnimationFrame(animationId)
if (renderer) {
renderer.dispose()
}
})
</script>
<style>
.canvas-container {
width: 100%;
height: 100vh;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
<template>
<div class="about">
<div ref="container" class="canvas-container"></div>
</div>
</template>
<script setup>
import { onMounted, onBeforeUnmount, ref } from 'vue'
import * as THREE from 'three'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
const container = ref(null)
let scene = null
let camera = null
let renderer = null
let mixer = null
let model = null
let animationId = null
const initScene = () => {
// 初始化场景
scene = new THREE.Scene()
scene.background = new THREE.Color(0xeeeeee)
// 初始化相机
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.set(5, 5, 5)
// 初始化渲染器
renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(container.value.clientWidth, container.value.clientHeight)
container.value.appendChild(renderer.domElement)
// 添加灯光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.8)
scene.add(ambientLight)
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5)
directionalLight.position.set(5, 5, 5)
scene.add(directionalLight)
}
const loadModel = () => {
const loader = new GLTFLoader()
// 替换成你的GLB模型路径
loader.load(
'/models/models.glb',
(gltf) => {
model = gltf.scene
scene.add(model)
// 如果有动画
if (gltf.animations.length > 0) {
mixer = new THREE.AnimationMixer(model)
const action = mixer.clipAction(gltf.animations[0])
action.play()
}
// 调整模型位置和缩放
model.position.set(5, 2, 0)
model.scale.set(5, 3, 1)
// 自动调整相机视角
const box = new THREE.Box3().setFromObject(model)
const center = box.getCenter(new THREE.Vector3())
camera.lookAt(center)
// 引入添加控制器,可以用鼠标控制模型
const controls = new OrbitControls(camera, renderer.domElement)
controls.target.copy(model.position)
controls.update()
controls.enableDamping = true
},
undefined,
(error) => {
console.error('Error loading model:', error)
}
)
}
const animate = () => {
// 更新动画
if (mixer) {
mixer.update(0.0167) // 60fps
}
renderer.render(scene, camera)
animationId = requestAnimationFrame(animate)
}
const handleResize = () => {
camera.aspect = container.value.clientWidth / container.value.clientHeight
camera.updateProjectionMatrix()
renderer.setSize(container.value.clientWidth, container.value.clientHeight)
}
onMounted(() => {
initScene()
loadModel()
animate()
window.addEventListener('resize', handleResize)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', handleResize)
cancelAnimationFrame(animationId)
if (renderer) {
renderer.dispose()
}
})
</script>
<style>
.canvas-container {
width: 100%;
height: 100vh;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>