three.js监听鼠标点击事件

优化了好几次的threejs中鼠标点击事件,直接上代码。

// 监听鼠标点击事件 展示详情页面
const onMouseClick = (event) => {
  let raycaster = new THREE.Raycaster()
  let mouse = new THREE.Vector2()
  // 通过鼠标点击的位置计算出raycaster所需要的点的位置,以屏幕中心为原点,值的范围为-1到1.
  let div3DLeft = div3D.getBoundingClientRect().left
  let div3DTop = div3D.getBoundingClientRect().top
  mouse.x = ((event.clientX - div3DLeft) / div3D.clientWidth) * 2 - 1
  mouse.y = -((event.clientY - div3DTop) / div3D.clientHeight) * 2 + 1
  // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
  raycaster.setFromCamera(mouse, camera)
  // 获取raycaster直线和所有模型相交的数组集合
  raycastMeshes(clickApp, raycaster)
}
function raycastMeshes (callback, raycaster) {
  let intersects = []
  // 获取整个场景
  let theScene = scene || new THREE.Scene()
  // 获取鼠标点击点的射线
  let theRaycaster = raycaster || new THREE.Raycaster()
  // 对场景及其子节点遍历
  for (let i in theScene.children) {
    // 如果场景的子节点是Group或者Scene对象
    if (theScene.children[i] instanceof THREE.Group || theScene.children[i] instanceof THREE.Scene) {
      // 场景子节点及其后代,被射线穿过的模型的数组集合
      // intersects = theRaycaster.intersectObjects(theScene.children[i].children, true)
      let rayArr = theRaycaster.intersectObjects(theScene.children[i].children, true)
      intersects.push(...rayArr)
    } else if (theScene.children[i] instanceof THREE.Mesh) {
      // 如果场景的子节点是Mesh网格对象,场景子节点被射线穿过的模型的数组集合
      // intersects.push(theRaycaster.intersectObject(theScene.children[i]))
    }
  }
  intersects = filtersVisibleFalse(intersects) // 过滤掉不可见的
  // 被射线穿过的模型的数组集合
  if (intersects && intersects.length > 0) {
    return callback(intersects)
  } else {
    // this.hiddenDetailDiv()
    return null
  }
}
function filtersVisibleFalse (arr) {
  let arrList = arr
  if (arr && arr.length > 0) {
    arrList = []
    for (let i = 0; i < arr.length; i++) {
      if (arr[i].object.visible) {
        arrList.push(arr[i])
      }
    }
  }
  return arrList
}
function clickApp (intersects) {
  let selectedObjects = null
  if (intersects[0].object !== undefined) {
    console.log(intersects[0].object, '这就是成功点击到的对象了~')
  }
}

说明注意:
1、div3D是挂载threejs的dom。
2、有些对象是包含了很多children的所以需要遍历,并push到intersects数组去重。
3、有些对象设置成了不可见,但是仍然会点击到,所以通过filtersVisibleFalse函数过滤。

你可能感兴趣的:(threejs)