效果预览
该场景是模拟两个楼层,当鼠标放到不同的楼层上时改变其透明度
blender中的模型如下图:
首先导入模型
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'
addfbx () {
const loader = new FBXLoader()
loader.load('/models/floor/楼层简易demo1.fbx', mesh => {
this.loaderMesh = mesh
mesh.scale.multiplyScalar(0.01)
this.scene.add(mesh)
}, undefined, function (error) {
console.error(error)
})
},
查看模型中有多少个物体
// 获取场景的物体
dumpObject (obj, lines = [], isLast = true, prefix = '') {
const localPrefix = isLast ? '└─' : '├─'
lines.push(`${prefix}${prefix ? localPrefix : ''}${obj.name || '*no-name*'} [${obj.type}]`)
const newPrefix = prefix + (isLast ? ' ' : '│ ')
const lastNdx = obj.children.length - 1
obj.children.forEach((child, ndx) => {
const isLast = ndx === lastNdx
this.dumpObject(child, lines, isLast, newPrefix) // 递归
})
return lines
}
并在addfbx中将mesh传入dumpObject,然后打印查看模型中的物体
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'
addfbx () {
const loader = new FBXLoader()
loader.load('/models/floor/楼层简易demo1.fbx', mesh => {
this.loaderMesh = mesh
mesh.scale.multiplyScalar(0.01)
this.scene.add(mesh)
// '平面001'是二楼;'平面'是一楼
mesh.children[0].material.transparent = true // 二楼
mesh.children[0].material.opacity = 0.5
mesh.children[2].material.transparent = true // 一楼
mesh.children[2].material.opacity = 0.5
console.log(this.dumpObject(mesh).join('\n'))
}, undefined, function (error) {
console.error(error)
})
},
打印结果如下:
可见我得模型中有两个平面,和一个灯光,和我们在blender里看到的一致。
“平面001”代表的是二楼;“平面”代表的是一楼
tips:
1.我这个场景比较简单,建议大家建模的时候把名字规范好,不然后面开发时会搞不清谁是谁;
2.另外建模时可以不要包含灯光,灯光可以在threeJS里再去加,这样mesh里只有物体会更方便我们操作一些
下面我们要对这两个平面进行操作,根据鼠标来改变它的透明度
鼠标监听,并进行相应的处理
// 添加鼠标监听
document.addEventListener('pointermove', this.onPointerMove)
onPointerMove (event) {
const pointer = new THREE.Vector2()
pointer.x = (event.clientX / window.innerWidth) * 2 - 1
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1
const raycaster = new THREE.Raycaster()
raycaster.setFromCamera(pointer, this.camera)
const intersects = raycaster.intersectObject(this.loaderMesh, true)
if (intersects.length > 0) {
// intersects[0].object.material.opacity = 1
this.loaderMesh.children.forEach(item => {
if (item.ID !== intersects[0].object.ID) {
// 让鼠标选中的这个物体透明度为1,其他物体为0.5
if (item.material) item.material.opacity = 0.5
} else {
if (item.material) item.material.opacity = 1
}
})
} else {
// 鼠标移出了模型,这时所有物体透明度都为0.5
this.loaderMesh.children.forEach(item => {
if (item.material) item.material.opacity = 0.5
})
}
}
注意一下:这里要改变物体的透明度,需要在前面导入模型时,将mesh的material.transparent改为true,否则直接改opacity会失效
到此,上述功能都已经实现了。