版本號:
vue:2.6.10
vue-cli3.x
three.js:0.115.0
引入方式:
import * as THREE from 'three'
import Stats from 'stats.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
模型目錄:
.glb經過了webpack的處理,需要把.obj文件放到vue中處理靜態文件的文件夾中,在vue-cli3中public文件夾下的文件不需要經過webpack處理,在vue-cli3.0之前就是放在static靜態文件文件夾下,在vue-cli3.0中需要放在public文件夾下,並且在組件中通過process.env.BASE_URL+public文件夾下的.obj文件的路徑來引用。
組件引用:
通過全局process.env.BASE_URL直接引入及可`${process.env.BASE_URL}model/Soldier.glb`
this.gltfLoader.load(
`${process.env.BASE_URL}model/Soldier.glb`,
gltf => {
alert('11')
gltf.scene.name = 'Soldier'
gltf.scene.rotation.y = Math.PI
this.scene.add(gltf.scene)
this.treeData = [gltf.scene]
this.scene.add(new AmbientLight(0xffffff, 2))
this.orbitControls.target.set(0, 1, 0)
const animationClip = gltf.animations.find(
animationClip => animationClip.name === 'Walk'
)
this.walkAction = this.animationMixer.clipAction(
animationClip
)
this.walkAction.play()
}
)
其他:
贈送一個官方的glb格式的文件
http://www.webgl3d.cn/threejs/examples/models/gltf/Soldier.glb
附上代碼
<template>
<div>
<el-row>
<el-col :span="5" class="left-trees">
</el-col>
<el-col :span="19">
<div id="container"></div>
</el-col>
</el-row>
</div>
</template>
<script>
import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
export default {
name: 'ThreeTest',
data() {
return {
}
},
methods: {
init() {
this.scene = new THREE.Scene()
this.clock = new THREE.Clock()
this.camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
100
)
console.log(Twidth, Theight)
this.renderer = new THREE.WebGLRenderer({ antialias: true })
this.gltfLoader = new GLTFLoader()
this.stlLoader = new STLLoader()
this.orbitControls = new OrbitControls(
this.camera,
this.renderer.domElement
)
this.animationMixer = new THREE.AnimationMixer(this.scene)
this.renderer.setSize(window.innerWidth, window.innerHeight)
// document.body.appendChild(this.renderer.domElement)
document
.getElementById('container')
.appendChild(this.renderer.domElement)
window.addEventListener('resize', () => this.onWindowResize())
this.camera.position.set(-0.5, 2, 1)
const planeBufferGeometry = new THREE.PlaneBufferGeometry(80, 80)
const plane = new THREE.Mesh(
planeBufferGeometry,
new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide
})
)
plane.name = 'plane'
plane.rotation.x = -Math.PI / 2
this.scene.add(plane)
this.scene.add(new THREE.GridHelper(10, 10))
this.gltfLoader.load(
`${process.env.BASE_URL}model/Soldier.glb`,
gltf => {
gltf.scene.name = 'Soldier'
gltf.scene.rotation.y = Math.PI
this.scene.add(gltf.scene)
this.treeData = [gltf.scene]
this.scene.add(new THREE.AmbientLight(0xffffff, 2))
this.orbitControls.target.set(0, 1, 0)
const animationClip = gltf.animations.find(
animationClip => animationClip.name === 'Walk'
)
this.walkAction = this.animationMixer.clipAction(
animationClip
)
this.walkAction.play()
}
)
this.renderer.domElement.addEventListener('click', event => {
const { offsetX, offsetY } = event
const x = (offsetX / window.innerWidth) * 2 - 1
const y = -(offsetY / window.innerHeight) * 2 + 1
const mousePoint = new THREE.Vector2(x, y)
const raycaster = new THREE.Raycaster()
// 設置鼠標位置和參考相機
raycaster.setFromCamera(mousePoint, this.camera)
// 鼠標點擊對應的物體(所有鼠標映射到的物體,包括被遮擋的)
const intersects = raycaster.intersectObjects(
this.scene.children,
true
)
// console.log(intersects)
// 過濾網格和地面
const intersect = intersects.filter(
intersect =>
!(intersect.object instanceof THREE.GridHelper) &&
intersect.object.name !== 'plane'
)[0]
if (intersect && this.isClickSoldier(intersect.object)) {
// 停止動畫
// this.walkAction.stop();
// 暫停動畫
this.walkAction.paused = !this.walkAction.paused
console.log(intersect)
intersect.object.material.color.set(0xff0000)
}
})
this.render()
},
isClickSoldier(object) {
if (object.name === 'Soldier') {
return object
} else if (object.parent) {
return this.isClickSoldier(object.parent)
} else {
return null
}
},
render() {
// 更新動畫
this.animationMixer.update(this.clock.getDelta())
this.renderer.render(this.scene, this.camera)
this.orbitControls.update()
window.requestAnimationFrame(() => this.render())
// this.stats.update()
},
onWindowResize() {
this.renderer.setSize(window.innerWidth, window.innerHeight)
this.camera.aspect = window.innerWidth / window.innerHeight
this.camera.updateProjectionMatrix()
},
},
mounted() {
this.init()
}
}
</script>
<style >
#container {
height: 400px;
}
</style>
還在摸索中可以交流哈