Skip to content

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>

程序员小洛文档