光线相交部分,光线投射用于进行鼠标拾取(在三维空间中计算出鼠标移过了什么物体)。
知识点:
- const raycaster = new THREE.Raycaster()
- raycaster.set(rayOrigin, rayDirection)
- raycaster.intersectObject([a,b,c, 经过光线的物体数组])
- raycaster.setFromCamera(mouse, camera)
// 创建一个光线投射
const raycaster = new THREE.Raycaster()
// 在动画函数中将处在光线上的物体变色
const clock = new THREE.Clock()
const tick = () => {
// 三个小球做不同速度的运动
const elapsedTime = clock.getElapsedTime()
object1.position.y = Math.sin(elapsedTime * 0.3) * 1.5
object2.position.y = Math.sin(elapsedTime * 0.3) * 1.5
object3.position.y = Math.sin(elapsedTime * 0.3) * 1.5
// 定义光线方向的两个点 创建向量
const rayOrigin = new THREE.Vector3(-3, 0, 0)
const rayDirection = new THREE.Vector3(1, 0, 0)
rayDirection.normalize() /* 三维向量处理成同方向 */
// 使用一个新的原点和方向来更新射线。
raycaster.set(rayOrigin, rayDirection)
// 将三个几个球体合并到一个数组中
const objectsToTest = [object1, object2, object3]
// 该方法返回一个包含有交叉部分的数组
const intersects = raycaster.intersectObject(objectsToTest)
// 先将所有的变为初始色
for(const object of objectsToTest) {
object.material.color.set('#ff0000')
}
// 将交叉部分的颜色变蓝
for(const intersect of intersects) {
intersect.object.material.color.set('#0000fff')
}
}
判断鼠标事件
// 监听鼠标事件,并将鼠标的移动值规范在-1——1之间
const mouse = new THREE.Vector2() /* 创建二维向量保存鼠标值 */
const currentIntersect = null /* 控制鼠标是否进入几何体的开关 */
// 鼠标移动
window.addEventListener('mousemove', (event) => {
mouse.x = event.clientX / window.innerWidth * 2 -1
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
})
// 点击事件
window.addEventListener('click', () => {
if(currentIntersect) {
switch(currentIntersect.object) {
case object1:
console.log('点击了第一个小球')
break
case object2:
console.log('点击了第二个小球')
break
case object3:
console.log('点击了第三个小球')
break
}
}
})
// 动画函数
const tick = () => {
// 三个小球做不同速度的运动
const elapsedTime = clock.getElapsedTime()
object1.position.y = Math.sin(elapsedTime * 0.3) * 1.5
object2.position.y = Math.sin(elapsedTime * 0.3) * 1.5
object3.position.y = Math.sin(elapsedTime * 0.3) * 1.5
// 使用一个新的原点和方向来更新射线。
raycaster.setFromCamera(mouse, camera)
const objectsToTest = [object1, object2, object3]
const intersects = raycaster.intersectObject(objectsToTest)
for(const object of objectsToTest) {
object.material.color.set('#ff0000')
}
for(const intersect of intersects) {
intersect.object.material.color.set('#0000fff')
}
// 通过光线是否有相交的物体判断光标是否在物体上
if(intersects.length) {
if(currentIntersect === null) {
console.log('鼠标进入')
}else {
console.log('鼠标悬停')
}
currentIntersect = intersects[0]
}else {
if(currentIntersect) {
console.log('鼠标离开')
}
currentIntersect = null
}
}